home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / pictex / addon / pictexwd.tex (.txt) < prev    next >
LaTeX Document  |  1994-04-19  |  133KB  |  3,246 lines

  1. % G"andertes PiCTeX.TEX mit weniger Dimensionsregistern %
  2. % von Andreas Schrell, ohne Gew"ahr!!!!!!!
  3. % Version 0.0 vom 31.03.1994
  4. % FEHLERMELDUNGEN an Andreas.Schrell@RS.maus.de
  5. % This is PiCTeXWD, Version 1.1   9/21/87
  6. % CAVEAT: The PiCTeX manual often has a more lucid explanation
  7. %   of any given topic than you will find in the internal documentation
  8. %   of the macros.
  9. % PiCTeX's commands can be classified into two groups: (1) public (or
  10. %   external), and (2) private (or internal). The public macros are
  11. %   discussed at length in the manual. The only discussion of the private
  12. %   macros is the internal documentation. The private macros all have
  13. %   names beginning with an exclamation point (!) of category code 11. 
  14. %   Since in normal usage "!" has category code 12, these macros can't
  15. %   be accessed or modified by the general user.
  16. % The macros are organized into thematically related groups. For example,
  17. %   the macros dealing with dots & dashes are all in the DASHPATTERN group.
  18. %   The table below shows which macros are in which groups. The table
  19. %   covers all public macros, and many (but not all) of PiCTeX's upper level
  20. %   private macros. Following the table, the various groups are listed
  21. %   in the order in which they appear in the table.
  22. % *********************** TABLE OF GROUPS OF MACROS **********************
  23. % HACKS:  Utility macros
  24. %    \PiC
  25. %    \PiCTeX
  26. %    \placevalueinpts 
  27. %    \!!loop 
  28. %    \!cfor
  29. %    \!copylist
  30. %    \!ecfor
  31. %    \!etfor
  32. %    \!getnext
  33. %    \!getnextvalueof
  34. %    \!ifempty
  35. %    \!ifnextchar
  36. %    \!leftappend
  37. %    \!listaddon 
  38. %    \!loop
  39. %    \!lop
  40. %    \!mlap
  41. %    \!not
  42. %    \!removept
  43. %    \!rightappend
  44. %    \!tfor 
  45. %    \!vmlap
  46. %    \!wlet
  47. % ALLOCATION:  Allocates registers
  48. % AREAS: Deals with plot areas 
  49. %    \axis
  50. %    \grid 
  51. %    \invisibleaxes
  52. %    \normalgraphs 
  53. %    \plotheading 
  54. %    \setplotarea
  55. %    \visibleaxes
  56. % ARROWS:  Draws arrows
  57. %    \arrow
  58. %    \betweenarrows
  59. % BARS:  Draws bars
  60. %    \putbar 
  61. %    \setbars
  62. % BOXES:  Draws rectangles
  63. %    \frame
  64. %    \putrectangle 
  65. %    \rectangle
  66. %    \shaderectangleson
  67. %    \shaderectanglesoff
  68. % CURVES:  Upper level plot commands
  69. %    \hshade 
  70. %    \plot 
  71. %    \sethistograms
  72. %    \setlinear
  73. %    \setquadratic
  74. %    \vshade
  75. % DASHPATTERNS:  Sets up dash patterns
  76. %    \findlength 
  77. %    \setdashes 
  78. %    \setdashesnear
  79. %    \setdashpattern
  80. %    \setdots 
  81. %    \setdotsnear 
  82. %    \setsolid
  83. %    \!dashingoff
  84. %    \!dashingon
  85. % DIVISION:  Does long division of dimension registers
  86. %    \Divide 
  87. %    \!divide
  88. % ELLIPSES:  Draws ellipses and circles
  89. %    \circulararc 
  90. %    \ellipticalarc 
  91. % RULES:  Draws rules, i.e., horizontal & vertical lines
  92. %    \putrule 
  93. %    \!putdashedhline
  94. %    \!putdashedvline
  95. %    \!puthline 
  96. %    \!putsolidhline  
  97. %    \!putsolidvline  
  98. %    \!putvline
  99. % LINEAR ARC:  Draws straight lines -- solid and dashed
  100. %    \inboundscheckoff
  101. %    \inboundscheckon
  102. %    \!advancedashing 
  103. %    \!drawlinearsegment
  104. %    \!initinboundscheck
  105. %    \!linearsolid
  106. %    \!lineardashed
  107. %    \!ljoin
  108. %    \!plotifinbounds     
  109. %    \!start 
  110. % LOGTEN:  Log_10 function
  111. %    \!logten
  112. % PICTURES:  Basic setups for PiCtures; \put commands
  113. %    \accountingoff
  114. %    \accountingon
  115. %    \beginpicture
  116. %    \endpicture    
  117. %    \endpicturesave 
  118. %    \lines
  119. %    \multiput
  120. %    \put 
  121. %    \setcoordinatemode
  122. %    \setcoordinatesystem
  123. %    \setdimensionmode
  124. %    \stack 
  125. %    \Lines
  126. %    \Xdistance
  127. %    \Ydistance
  128. %    \!dimenput
  129. %    \!ifcoordmode
  130. %    \!ifdimenmode
  131. %    \!setcoordmode
  132. %    \!setdimenmode
  133. %    \!setputobject
  134. % PLOTTING:  Things to do with plotting
  135. %    \dontsavelinesandcurves
  136. %    \replot
  137. %    \savelinesandcurves 
  138. %    \setplotsymbol
  139. %    \writesavefile 
  140. %    \!plot
  141. % PYTHAGORAS:  Euclidean distance function
  142. %    \placehypotenuse 
  143. %    \!Pythag
  144. % QUADRATIC ARC:  Draws a quadratic arc
  145. %    \!qjoin 
  146. % ROTATIONS:  Handles rotations
  147. %    \startrotation 
  148. %    \stoprotation
  149. %    \!rotateaboutpivot
  150. %    \!rotateonly
  151. % SHADING:  Handles shading
  152. %    \setshadegrid 
  153. %    \setshadesymbol
  154. %    \!lshade
  155. %    \!qshade
  156. %    \!starthshade
  157. %    \!startvshade  
  158. % TICKS:  Draws ticks on graphs
  159. %    \gridlines
  160. %    \loggedticks
  161. %    \nogridlines
  162. %    \ticksin
  163. %    \ticksout
  164. %    \unloggesticks
  165. % ***************** END OF TABLE OF GROUPS OF MACROS ********************
  166. \catcode`!=11 %  ***** THIS MUST NEVER BE OMITTED
  167. % *******************************
  168. % *** HACKS  (Utility macros) ***
  169. % *******************************
  170. % ** User commands
  171. % **   \PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC}
  172. % **   \PiCTeX{\PiC\kern-.11em\TeX}
  173. % **   \placevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE}
  174. % ** Internal commands
  175. % **   \!ifnextchar{CHARACTER}{TRUE ACTION}{FALSE ACTION}
  176. % **   \!tfor NAME := LIST \do {BODY}
  177. % **   \!etfor NAME:= LIST \do {BODY}
  178. % **   \!cfor NAME := LIST \do {BODY}
  179. % **   \!ecfor NAME:= LIST \do {BODY}
  180. % **   \!ifempty{MACRO}{TRUE ACTION}{FALSE ACTION}
  181. % **   \!getnext\\ITEMfrom\LIST
  182. % **   \!getnextvalueof\DIMEN\from\LIST
  183. % **   \!copylist\LISTMACRO_A\to\LISTMACRO_B
  184. % **   \!wlet\CONTROL_SEQUENCE_A=\CONTROL_SEQUENCE_B
  185. % **   \!listaddon ITEM LIST
  186. % **   \!rightappendITEM\withCS\to\LISTMACRO
  187. % **   \!leftappendITEM\withCS\to\LISTMACRO
  188. % **   \!lop\LISTMACRO\to\ITEM
  189. % **   \!loop ... repeat
  190. % **   \!!loop ... repeat
  191. % **   \!removept{DIMENSION REGISTER}{CONTROL SEQUENCE}
  192. % **   \!mlap{...}  
  193. % **   \!vmlap{...}
  194. % **   \!not{TEK if-CONDITION}
  195. % ** First, here are the the PiCTeX logo, and the syllable PiC:
  196. \def\PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC}
  197. \def\PiCTeX{\PiC\kern-.11em\TeX}
  198. % ** The following macro expands to parameter #2 or parameter #3 according to
  199. % ** whether the next non-blank character following the macro is or is not #1. 
  200. % ** Blanks following the macro are gobbled.
  201. \def\!ifnextchar#1#2#3{%
  202.   \let\!testchar=#1%
  203.   \def\!first{#2}%
  204.   \def\!second{#3}%
  205.   \futurelet\!nextchar\!testnext}
  206. \def\!testnext{%
  207.   \ifx \!nextchar \!spacetoken 
  208.     \let\!next=\!skipspacetestagain
  209.   \else
  210.     \ifx \!nextchar \!testchar
  211.       \let\!next=\!first
  212.     \else 
  213.       \let\!next=\!second 
  214.     \fi 
  215.   \fi
  216.   \!next}
  217. \def\\{\!skipspacetestagain} 
  218.   \expandafter\def\\ {\futurelet\!nextchar\!testnext} 
  219. \def\\{\let\!spacetoken= } \\  %  ** set \spacetoken to a space token
  220. % ** Borrow the "tfor" macro from Latex:
  221. % **   \!tfor NAME := LIST \do {BODY}
  222. % **   if, before expansion, LIST = T1 ... Tn,  where each  Ti  is a token
  223. % **   or  {...},  then executes  BODY  n  times, with  NAME = Ti  on the
  224. % **   i-th iteration.  Works for  n=0.
  225. \def\!tfor#1:=#2\do#3{%
  226.   \edef\!fortemp{#2}%
  227.   \ifx\!fortemp\!empty 
  228.     \else
  229.     \!tforloop#2\!nil\!nil\!!#1{#3}%
  230.   \fi}
  231. \def\!tforloop#1#2\!!#3#4{%
  232.   \def#3{#1}%
  233.   \ifx #3\!nnil
  234.     \let\!nextwhile=\!fornoop
  235.   \else
  236.     #4\relax
  237.     \let\!nextwhile=\!tforloop
  238.   \fi 
  239.   \!nextwhile#2\!!#3{#4}}
  240. % **   \!etfor NAME:= LIST\do {BODY}
  241. % **   This is like \!cfor, but LIST is any balanced token list whose complete
  242. % **     expansion has the form  T1 ... Tn
  243. \def\!etfor#1:=#2\do#3{%
  244.   \def\!!tfor{\!tfor#1:=}%
  245.   \edef\!!!tfor{#2}%
  246.   \expandafter\!!tfor\!!!tfor\do{#3}}
  247. % **   modify the Latex \tfor (token-for) loop to a \cfor (comma-for) loop.
  248. % **   \!cfor NAME := LIST \do {BODY}
  249. % **     if, before expansion, LIST = a1,a2,...an, then executes  BODY n times,
  250. % **     with  NAME = ai  on the i-th iteration.  Works for  n=0.
  251. \def\!cfor#1:=#2\do#3{%
  252.   \edef\!fortemp{#2}%
  253.   \ifx\!fortemp\!empty 
  254.   \else
  255.     \!cforloop#2,\!nil,\!nil\!!#1{#3}%
  256.   \fi}
  257. \def\!cforloop#1,#2\!!#3#4{%
  258.   \def#3{#1}%
  259.   \ifx #3\!nnil
  260.     \let\!nextwhile=\!fornoop 
  261.   \else
  262.     #4\relax
  263.     \let\!nextwhile=\!cforloop
  264.   \fi
  265.   \!nextwhile#2\!!#3{#4}}
  266. % **   \!ecfor NAME:= LIST\do {BODY}
  267. % **   This is like \!cfor, but LIST is any balanced token list whose complete
  268. % **     expansion has the form  a1,a2,...,an.
  269. \def\!ecfor#1:=#2\do#3{%
  270.   \def\!!cfor{\!cfor#1:=}%
  271.   \edef\!!!cfor{#2}%
  272.   \expandafter\!!cfor\!!!cfor\do{#3}}
  273. \def\!empty{}
  274. \def\!nnil{\!nil}
  275. \def\!fornoop#1\!!#2#3{}
  276. % **  \!ifempty{ARG}{TRUE ACTION}{FALSE ACTION}
  277. \def\!ifempty#1#2#3{%
  278.   \edef\!emptyarg{#1}%
  279.   \ifx\!emptyarg\!empty
  280.     #2%
  281.   \else
  282.     #3%
  283.   \fi}
  284. % **  \!getnext\\ITEMfrom\LIST
  285. % **    \LIST has the form \\{item1}\\{item2}\\{item3}...\\{itemk}
  286. % **    This routine sets \ITEM to item1, and cycles \LIST to
  287. % **    \\{item2}\\{item3}...\\{itemk}\\{item1}
  288. \def\!getnext#1\from#2{%
  289.   \expandafter\!gnext#2\!#1#2}%
  290. \def\!gnext\\#1#2\!#3#4{%
  291.   \def#3{#1}%
  292.   \def#4{#2\\{#1}}%
  293.   \ignorespaces}
  294. % ** \!getnextvalueof\DIMEN\from\LIST
  295. % **   Similar to !getnext.  
  296. % **   \LIST has the form \\{dimen1}\\{dimen2}\\{dimen3} ... 
  297. % **   \DIMEN is a dimension register
  298. % **   Works also for counts
  299. \def\!getnextvalueof#1\from#2{%
  300.   \expandafter\!gnextv#2\!#1#2}%
  301. \def\!gnextv\\#1#2\!#3#4{%
  302.   #3=#1%
  303.   \def#4{#2\\{#1}}%
  304.   \ignorespaces}
  305. % ** \!copylist\LISTMACROA\to\LISTMACROB
  306. % **   makes the replacement text of LISTMACRO B identical to that of
  307. % **   list macro A.
  308. \def\!copylist#1\to#2{%
  309.   \expandafter\!!copylist#1\!#2}
  310. \def\!!copylist#1\!#2{%
  311.   \def#2{#1}\ignorespaces}
  312. % **  \!wlet\CSA=\CSB
  313. % **  lets control sequence \CSB = control sequence \CSA, and writes a
  314. % **    message to that effect in the log file using plain TEK's \wlog
  315. \def\!wlet#1=#2{%
  316.   \let#1=#2 
  317.   \wlog{\string#1=\string#2}}
  318. % ** \!listaddon ITEM LIST
  319. % ** LIST <-- LIST \\ ITEM
  320. \def\!listaddon#1#2{%
  321.   \expandafter\!!listaddon#2\!{#1}#2}
  322. \def\!!listaddon#1\!#2#3{%
  323.   \def#3{#1\\#2}}
  324. % **  \!rightappendITEM\to\LISTMACRO
  325. % **    \LISTMACRO --> \LISTMACRO\\{ITEM}
  326. %\def\!rightappend#1\to#2{\expandafter\!!rightappend#2\!{#1}#2}
  327. %\def\!!rightappend#1\!#2#3{\def#3{#1\\{#2}}}
  328. % **  \!rightappendITEM\withCS\to\LISTMACRO
  329. % **    \LISTMACRO --> \LISTMACRO||CS||{ITEM}
  330. \def\!rightappend#1\withCS#2\to#3{\expandafter\!!rightappend#3\!#2{#1}#3}
  331. \def\!!rightappend#1\!#2#3#4{\def#4{#1#2{#3}}}
  332. % **  \!leftappendITEM\withCS\to\LISTMACRO
  333. % **    \LISTMACRO --> CS||{ITEM}||\LISTMACRO
  334. \def\!leftappend#1\withCS#2\to#3{\expandafter\!!leftappend#3\!#2{#1}#3}
  335. \def\!!leftappend#1\!#2#3#4{\def#4{#2{#3}#1}}
  336. % **  \!lop\LISTMACRO\to\ITEM
  337. % **    \\{item1}\\{item2}\\{item3} ... --> \\{item2}\\{item3} ...
  338. % **    item1 --> \ITEM
  339. \def\!lop#1\to#2{\expandafter\!!lop#1\!#1#2}
  340. \def\!!lop\\#1#2\!#3#4{\def#4{#1}\def#3{#2}}
  341. % **  \!placeNUMBER\of\LISTMACRO\in\ITEM
  342. % **    the NUMBERth item of \LISTMACRO --> replacement text of \ITEM
  343. %\def\!place#1\of#2\in#3{\def#3{\outofrange}%
  344. %{\count0=#1\def\\##1{\advance\count0-1 \ifnum\count0=0 \gdef#3{##1}\fi}#2}}
  345. % **  Following code converts a commalist to a list macro, with all items 
  346. % **    fully expanded.
  347. %\!ecfor\item:=\commalist\do{\expandafter\!rightappend\item\to\list}
  348. % ** \!loop ... repeat
  349. % ** This is exactly like TEX's \loop ... repeat.  It can be used in nesting
  350. % ** two loops, without puting the inner one inside a group.
  351. \def\!loop#1\repeat{\def\!body{#1}\!iterate}
  352. \def\!iterate{\!body\let\!next=\!iterate\else\let\!next=\relax\fi\!next}
  353. % ** \!!loop ... repeat
  354. % ** This is exactly like TEX's \loop ... repeat.  It can be used in nesting
  355. % ** two loops, without puting the inner one inside a group.
  356. \def\!!loop#1\repeat{\def\!!body{#1}\!!iterate}
  357. \def\!!iterate{\!!body\let\!!next=\!!iterate\else\let\!!next=\relax\fi\!!next}
  358. %  (\multiput uses \!!loop)
  359. % ** \!removept{DIMENREG}{\CS}
  360. % ** Defines the control sequence CS to be the value (in points) in the
  361. % ** dimension register DIMENREG (but without the "pt" TEK usually adds)
  362. % ** E.g., after  \dimen0=12.3pt \!removept\dimen0\A, \A expands to 12.3
  363. \def\!removept#1#2{\edef#2{\expandafter\!!removePT\the#1}}
  364. {\catcode`p=12 \catcode`t=12 \gdef\!!removePT#1pt{#1}}
  365. % ** \pladevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE}
  366. \def\placevalueinpts of <#1> in #2 {%
  367.   \!removept{#1}{#2}}
  368. % ** \!mlap{...}  \!vmlap{...}
  369. % ** Center  ...  in a box of width 0.
  370. \def\!mlap#1{\hbox to 0pt{\hss#1\hss}}
  371. \def\!vmlap#1{\vbox to 0pt{\vss#1\vss}}
  372. % ** \!not{TEK if-CONDITION}
  373. % ** By a TEK if-CONDITION is meant something like 
  374. % **     \ifnum\N<0,   or   \ifdim\A>\B
  375. % ** \!not produces an if-condition which is false if the original condition
  376. % ** is true, and true if the original condition is false.
  377. \def\!not#1{%
  378.   #1\relax
  379.     \!switchfalse
  380.   \else
  381.     \!switchtrue
  382.   \fi
  383.   \if!switch
  384.   \ignorespaces}
  385. % *******************
  386. % *** ALLOCATIONS ***
  387. % *******************
  388. % This section allocates all the registers PiCTeX uses. Following
  389. % each allocation is a string of the form  ....N.D...L......... ;
  390. % the various letters show which sections of PiCTeX make explicit
  391. % reference to that register, according to the following code:
  392. %   H Hacks
  393. %   A Areas
  394. %   W arroWs
  395. %   B Bars
  396. %   X boXes
  397. %   C Curves
  398. %   D Dashpattterns
  399. %   V diVision
  400. %   E Ellipses
  401. %   U rUles
  402. %   L Linear arc
  403. %   G loGten
  404. %   P Pictures
  405. %   O plOtting
  406. %   Y pYthagoras
  407. %   Q Quadratic arc
  408. %   R Rotations
  409. %   S Shading
  410. %   T Ticks
  411. % Turn off messages from TeX's allocation macros
  412. \let\!!!wlog=\wlog              % "\wlog" is defined in plain TeX
  413. \def\wlog#1{}    
  414. \newskip\headingtoplotskip      %.A.................    %-as-%
  415. \newskip\linethickness         %.A..X....U........T
  416. \newskip\longticklength         %.A................T    %-as-%
  417. \newskip\plotsymbolspacing     %......D...L....Q...
  418. \newskip\shortticklength        %.A................T    %-as-%
  419. \newskip\stackleading           %.A..........P......    %-as-%
  420. \newskip\tickstovaluesleading   %.A................T    %-as-%
  421. \newskip\totalarclength        %......D...L....Q...
  422. \newskip\valuestolabelleading   %.A.................    %-as-%
  423. \newbox\!boxA                   %.AW...............T
  424. \newbox\!boxB                   %..W................
  425. \newbox\!picbox                 %............P......
  426. \newbox\!plotsymbol             %..........L..O.....
  427. \newbox\!putobject              %............PO...S.
  428. \newbox\!shadesymbol            %.................S.
  429. \newcount\!countA               %.A....D..UL....Q.ST
  430. \newcount\!countB               %......D..U.....Q.ST
  431. \newcount\!countC               %...............Q..T
  432. \newcount\!countD               %...................
  433. \newcount\!countE               %.............O....T
  434. \newcount\!countF               %.............O....T
  435. \newcount\!countG               %..................T
  436. \newcount\!fiftypt              %.........U.........
  437. \newcount\!intervalno           %..........L....Q...
  438. \newcount\!npoints              %..........L........
  439. \newcount\!nsegments            %.........U.........
  440. \newcount\!ntemp                %............P......
  441. \newcount\!parity               %.................S.
  442. \newcount\!scalefactor          %..................T
  443. \newcount\!tickcase             %..................T
  444. \newskip\!Xleft                %............P......
  445. \newskip\!Xright               %............P......
  446. \newskip\!Xsave                %.A................T
  447. \newskip\!Ybot                 %............P......
  448. \newskip\!Ysave                %.A................T
  449. \newskip\!Ytop                 %............P......
  450. \newskip\!angle                %........E..........
  451. \newskip\!arclength            %..W......UL....Q...
  452. \newskip\!areabloc             %.A........L........
  453. \newskip\!arealloc             %.A........L........
  454. \newskip\!arearloc             %.A........L........
  455. \newskip\!areatloc             %.A........L........
  456. \newskip\!bshrinkage           %.................S.
  457. \newskip\!checkbot             %..........L........
  458. \newskip\!checkleft            %..........L........
  459. \newskip\!checkright           %..........L........
  460. \newskip\!checktop             %..........L........
  461. \newdimen\!dimenA               %.AW.X.DVEUL..OYQRST
  462. \newdimen\!dimenB               %....X.DVEU...O.QRS.
  463. \newdimen\!dimenC               %..W.X.DVEU......RS.
  464. \newdimen\!dimenD               %..W.X.DVEU....Y.RS.
  465. \newdimen\!dimenE               %..W........G..YQ.S.
  466. \newdimen\!dimenF               %...........G..YQ.S.
  467. \newdimen\!dimenG               %...........G..YQ.S.
  468. \newdimen\!dimenH               %...........G..Y..S.
  469. \newdimen\!dimenI               %...BX.........Y....
  470. \newdimen\!distacross           %..........L....Q...
  471. \newdimen\!downlength           %..........L........
  472. \newdimen\!dp                   %.A..X.......P....S.
  473. \newdimen\!dshade               %.................S.
  474. \newdimen\!dxpos                %..W......U..P....S.
  475. \newdimen\!dxprime              %...............Q...
  476. \newdimen\!dypos                %..WB.....U..P......
  477. \newdimen\!dyprime              %...............Q...
  478. \newdimen\!ht                   %.A..X.......P....S.
  479. \newdimen\!leaderlength         %......D..U.........
  480. \newdimen\!lshrinkage           %.................S.
  481. \newdimen\!midarclength         %...............Q...
  482. \newdimen\!offset               %.A................T
  483. \newdimen\!plotheadingoffset    %.A.................
  484. \newdimen\!plotsymbolxshift     %..........L..O.....
  485. \newdimen\!plotsymbolyshift     %..........L..O.....
  486. \newdimen\!plotxorigin          %..........L..O.....
  487. \newdimen\!plotyorigin          %..........L..O.....
  488. \newdimen\!rshrinkage           %.................S.
  489. \newdimen\!shadesymbolxshift    %.................S.
  490. \newdimen\!shadesymbolyshift    %.................S.
  491. \newdimen\!tshrinkage           %.................S.
  492. \newdimen\!uplength             %..........L........
  493. \newdimen\!wd                   %....X.......P....S.
  494. \newdimen\!xB                   %...............Q...
  495. \newdimen\!xC                   %...............Q...
  496. \newdimen\!xE                   %..W.....E.L....Q.S.
  497. \newdimen\!xM                   %..W.....E......Q.S.
  498. \newdimen\!xS                   %..W.....E.L....Q.S.
  499. \newdimen\!xaxislength          %.A................T
  500. \newdimen\!xdiff                %..........L........
  501. \newdimen\!xleft                %............P......
  502. \newdimen\!xloc                 %..WB.....U.......S.
  503. \newdimen\!xorigin              %.A........L.P....S.
  504. \newdimen\!xpivot               %................R..
  505. \newdimen\!xpos                 %..........L.P..Q.ST
  506. \newdimen\!xprime               %...............Q...
  507. \newdimen\!xright               %............P......
  508. \newdimen\!xshade               %.................S.
  509. \newdimen\!xshift               %..W.........PO...S.
  510. \newdimen\!xtemp                %............P......
  511. \newdimen\!xunit                %.AWBX...EUL.P..QRS.
  512. \newdimen\!xxE                  %........E..........
  513. \newdimen\!xxM                  %........E..........
  514. \newdimen\!xxS                  %........E..........
  515. \newdimen\!xxloc                %..WB....EU.........
  516. \newdimen\!yB                   %...............Q...
  517. \newdimen\!yC                   %...............Q...
  518. \newdimen\!yE                   %..W.....E.L....Q...
  519. \newdimen\!yM                   %..W.....E......Q...
  520. \newdimen\!yS                   %..W.....E.L....Q...
  521. \newdimen\!yaxislength          %.A................T
  522. \newdimen\!ybot                 %............P......
  523. \newdimen\!ydiff                %..........L........
  524. \newdimen\!yloc                 %..WB.....U.......S.
  525. \newdimen\!yorigin              %.A........L.P....S.
  526. \newdimen\!ypivot               %................R..
  527. \newdimen\!ypos                 %..........L.P..Q.ST
  528. \newdimen\!yprime               %...............Q...
  529. \newdimen\!yshade               %.................S.
  530. \newdimen\!yshift               %..W.........PO...S.
  531. \newdimen\!ytemp                %............P......
  532. \newdimen\!ytop                 %............P......
  533. \newdimen\!yunit                %.AWBX...EUL.P..QRS.
  534. \newdimen\!yyE                  %........E..........
  535. \newdimen\!yyM                  %........E..........
  536. \newdimen\!yyS                  %........E..........
  537. \newdimen\!yyloc                %..WB....EU.........
  538. \newif\if!axisvisible           %.A.................
  539. \newif\if!gridlinestoo          %..................T
  540. \newif\if!keepPO                %...................
  541. \newif\if!placeaxislabel        %.A.................
  542. \newif\if!switch                %H..................
  543. \newif\if!xswitch               %.A................T
  544. \newtoks\!axisLaBeL             %.A.................
  545. \newtoks\!keywordtoks           %.A.................
  546. \newwrite\!replotfile           %.............O.....
  547. \newhelp\!keywordhelp{The keyword mentioned in the error message in unknown. 
  548. Replace NEW KEYWORD in the indicated response by the keyword that 
  549. should have been specified.}    %.A.................
  550. % The following commands assign alternate names to some of the 
  551. % above registers.  "\!wlet"  is defined in  Hacks.
  552. \!wlet\!!origin=\!xM                   %.A................T
  553. \!wlet\!!unit=\!uplength               %.A................T
  554. \!wlet\!Lresiduallength=\!dimenG       %.........U.........
  555. \!wlet\!Rresiduallength=\!dimenF       %.........U.........
  556. \!wlet\!axisLength=\!distacross        %.A................T
  557. \!wlet\!axisend=\!ydiff                %.A................T
  558. \!wlet\!axisstart=\!xdiff              %.A................T
  559. \!wlet\!axisxlevel=\!arclength         %.A................T
  560. \!wlet\!axisylevel=\!downlength        %.A................T
  561. \!wlet\!beta=\!dimenE                  %...............Q...
  562. \!wlet\!gamma=\!dimenF                 %...............Q...
  563. \!wlet\!shadexorigin=\!plotxorigin     %.................S.
  564. \!wlet\!shadeyorigin=\!plotyorigin     %.................S.
  565. \!wlet\!ticklength=\!xS                %..................T
  566. \!wlet\!ticklocation=\!xE              %..................T
  567. \!wlet\!ticklocationincr=\!yE          %..................T
  568. \!wlet\!tickwidth=\!yS                 %..................T
  569. \!wlet\!totalleaderlength=\!dimenE     %.........U.........
  570. \!wlet\!xone=\!xprime                  %....X..............
  571. \!wlet\!xtwo=\!dxprime                 %....X..............
  572. \!wlet\!ySsave=\!yM                    %...................
  573. \!wlet\!ybB=\!yB                       %.................S.
  574. \!wlet\!ybC=\!yC                       %.................S.
  575. \!wlet\!ybE=\!yE                       %.................S.
  576. \!wlet\!ybM=\!yM                       %.................S.
  577. \!wlet\!ybS=\!yS                       %.................S.
  578. \!wlet\!ybpos=\!yyloc                  %.................S.
  579. \!wlet\!yone=\!yprime                  %....X..............
  580. \!wlet\!ytB=\!xB                       %.................S.
  581. \!wlet\!ytC=\!xC                       %.................S.
  582. \!wlet\!ytE=\!downlength               %.................S.
  583. \!wlet\!ytM=\!arclength                %.................S.
  584. \!wlet\!ytS=\!distacross               %.................S.
  585. \!wlet\!ytpos=\!xxloc                  %.................S.
  586. \!wlet\!ytwo=\!dyprime                 %....X..............
  587. % Initial values for registers
  588. \def\!zpt{0pt}                              % static
  589. \!xunit=1pt
  590. \!yunit=1pt
  591. \!arearloc=\!xunit
  592. \!areatloc=\!yunit
  593. \!dshade=5pt
  594. \!leaderlength=24in
  595. \def\!tfs{256}                              % static
  596. \def\!wmax{5.3pt}                           % static
  597. \def\!wmin{2.7pt}                           % static
  598. \!xaxislength=\!xunit
  599. \!xpivot=\!zpt
  600. \!yaxislength=\!yunit 
  601. \!ypivot=\!zpt
  602. \plotsymbolspacing=.4pt
  603.   \!dimenA=50pt \def\!fiftypt{\the\!dimenA}     % static
  604. \def\!rootten{3.162278pt}                   % static
  605. \def\!tenAa{8.690286pt}                     % static  (A5)
  606. \def\!tenAc{2.773839pt}                     % static  (A3)
  607. \def\!tenAe{2.543275pt}                     % static  (A1)
  608. % Initial values for control sequences
  609. \def\!cosrotationangle{1}      %................R..
  610. \def\!sinrotationangle{0}      %................R..
  611. \def\!xpivotcoord{0}           %................R..
  612. \def\!xref{0}                  %............P......
  613. \def\!xshadesave{0}            %.................S.
  614. \def\!ypivotcoord{0}           %................R..
  615. \def\!yref{0}                  %............P......
  616. \def\!yshadesave{0}            %.................S.
  617. \def\!zero{0}                  %..................T
  618. % Reset TeX to report allocations
  619. \let\wlog=\!!!wlog
  620. %  *************************************
  621. %  ***  AREAS: Deals with plot areas ***
  622. %  *************************************
  623. %  ** User commands
  624. %  **   \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD
  625. %  **      to TOP YCOORD
  626. %  **   \axis BOTTOM-LEFT-TOP-RIGHT  [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE]
  627. %  **      [LABEL {label}] [TICKS] /
  628. %  **   \visibleaxes
  629. %  **   \invisibleaxes
  630. %  **   \plotheading {HEADING}
  631. %  **   \grid {# of columns} {# of rows}
  632. %  **   \normalgraphs 
  633. %  **  \normalgraphs
  634. %  **    Sets defaults for graph setup. See Subsection 3.4 of manual.
  635. \def\normalgraphs{%
  636.   \longticklength=.4\baselineskip
  637.   \shortticklength=.25\baselineskip
  638.   \tickstovaluesleading=.25\baselineskip
  639.   \valuestolabelleading=.8\baselineskip
  640.   \linethickness=.4pt
  641.   \stackleading=.17\baselineskip
  642.   \headingtoplotskip=1.5\baselineskip
  643.   \visibleaxes
  644.   \ticksout
  645.   \nogridlines
  646.   \unloggedticks}
  647. % **  \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD
  648. % **    to TOP YCOORD
  649. % **  Reserves space in PICBOX for a rectangular box with the indicated
  650. % **   coordinates.  Must be specified before calls to  \axis, 
  651. % **   \grid, \plotheading.
  652. % **  See Subsection 3.1 of the manual.
  653. \def\setplotarea x from #1 to #2, y from #3 to #4 {%
  654.   \!arealloc=\!M{#1}\!xunit \advance \!arealloc -\!xorigin
  655.   \!areabloc=\!M{#3}\!yunit \advance \!areabloc -\!yorigin
  656.   \!arearloc=\!M{#2}\!xunit \advance \!arearloc -\!xorigin
  657.   \!areatloc=\!M{#4}\!yunit \advance \!areatloc -\!yorigin
  658.   \!initinboundscheck
  659.   \!xaxislength=\!arearloc  \advance\!xaxislength -\!arealloc
  660.   \!yaxislength=\!areatloc  \advance\!yaxislength -\!areabloc
  661.   \!plotheadingoffset=\!zpt
  662.   \!dimenput {{\setbox0=\hbox{}\wd0=\!xaxislength\ht0=\!yaxislength\box0}}
  663.      [bl] (\!arealloc,\!areabloc)}
  664. % ** \visibleaxes, \invisibleaxes 
  665. % ** Switches for setting visibility of subsequent axes.
  666. % ** See Subsection 3.2 of the manual.
  667. \def\visibleaxes{%
  668.   \def\!axisvisibility{\!axisvisibletrue}}
  669. \def\invisibleaxes{%
  670.   \def\!axisvisibility{\!axisvisiblefalse}}
  671. % ** The next few macros enable the user to fix up an erroneous keyword
  672. % **   in the \axis command.
  673. %  \newhelp is in ALLOCATIONS
  674. %  \newhelp\!keywordhelp{The keyword mentioned in the error message in unknown. 
  675. %  Replace NEW KEYWORD in the indicated response by the keyword that 
  676. %  should have been specified.}
  677. \def\!fixkeyword#1{%
  678.   \errhelp=\!keywordhelp
  679.   \errmessage{Unrecognized keyword `#1': \the\!keywordtoks{NEW KEYWORD}'}}
  680. %  \newtoks\!keywordtoks    In ALLOCATIONS.
  681. \!keywordtoks={enter `i\fixkeyword}
  682. \def\fixkeyword#1{%
  683.   \!nextkeyword#1 }
  684. % ** \axis BOTTOM-LEFT-TOP-RIGHT  [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE]
  685. % **   [LABEL {label}] [TICKS] /
  686. % ** Exactly one of the keywords BOTTOM, LEFT, TOP, RIGHT must be
  687. % ** specified. Axis is drawn along the indicated edge of the current
  688. % ** plot area, shifted if the SHIFTEDTO option is used, visible or
  689. % ** invisible according the selected option, with an optional LABEL,
  690. % ** and optional TICKS (see ticks.tex for the options avialabel with
  691. % ** TICKS). The TICKS option must be the last one specified. The \axis
  692. % ** MUST be terminated with a / followed by a space.
  693. % ** See Subsection 3.2 of the manual for more information.
  694. % ** The various options of the \axis command are processed by the
  695. % ** \!nextkeyword macro defined below. For example, 
  696. % ** `\!nextkeyword shiftedto ' expands to `\!axisshiftedto'.
  697. \def\axis {%
  698.   \def\!nextkeyword##1 {%
  699.     \expandafter\ifx\csname !axis##1\endcsname \relax
  700.       \def\!next{\!fixkeyword{##1}}%
  701.     \else
  702.       \def\!next{\csname !axis##1\endcsname}%
  703.     \fi
  704.     \!next}%
  705.   \!offset=\!zpt
  706.   \!axisvisibility
  707.   \!placeaxislabelfalse
  708.   \!nextkeyword}
  709. % ** This and the various macros that follow handle the keyword
  710. % ** specifications on the \axis command
  711. % ** See Subsection 3.2 of the manual.
  712. \def\!axisbottom{%
  713.   \!axisylevel=\!areabloc
  714.   \def\!tickxsign{0}%
  715.   \def\!tickysign{-}%
  716.   \def\!axissetup{\!axisxsetup}%
  717.   \def\!axislabeltbrl{t}%
  718.   \!nextkeyword}
  719. \def\!axistop{%
  720.   \!axisylevel=\!areatloc
  721.   \def\!tickxsign{0}%
  722.   \def\!tickysign{+}%
  723.   \def\!axissetup{\!axisxsetup}%
  724.   \def\!axislabeltbrl{b}%
  725.   \!nextkeyword}
  726. \def\!axisleft{%
  727.   \!axisxlevel=\!arealloc
  728.   \def\!tickxsign{-}%
  729.   \def\!tickysign{0}%
  730.   \def\!axissetup{\!axisysetup}%
  731.   \def\!axislabeltbrl{r}%
  732.   \!nextkeyword}
  733. \def\!axisright{%
  734.   \!axisxlevel=\!arearloc
  735.   \def\!tickxsign{+}%
  736.   \def\!tickysign{0}%
  737.   \def\!axissetup{\!axisysetup}%
  738.   \def\!axislabeltbrl{l}%
  739.   \!nextkeyword}
  740. \def\!axisshiftedto#1=#2 {%
  741.   \if 0\!tickxsign
  742.     \!axisylevel=\!M{#2}\!yunit
  743.     \advance\!axisylevel -\!yorigin
  744.   \else
  745.     \!axisxlevel=\!M{#2}\!xunit
  746.     \advance\!axisxlevel -\!xorigin
  747.   \fi
  748.   \!nextkeyword}
  749. \def\!axisvisible{%
  750.   \!axisvisibletrue  
  751.   \!nextkeyword}
  752. \def\!axisinvisible{%
  753.   \!axisvisiblefalse
  754.   \!nextkeyword}
  755. \def\!axislabel#1 {%
  756.   \!axisLaBeL={#1}%
  757.   \!placeaxislabeltrue
  758.   \!nextkeyword}
  759. \expandafter\def\csname !axis/\endcsname{%
  760.   \!axissetup % This could done already by "ticks"; if so, now \relax
  761.   \if!placeaxislabel
  762.     \!placeaxislabel
  763.   \fi
  764.   \if +\!tickysign %                 ** (A "top" axis)
  765.     \!dimenA=\!axisylevel
  766.     \advance\!dimenA \!offset %      ** dimA = top of the axis structure
  767.     \advance\!dimenA -\!areatloc %   ** dimA = excess over the plot area
  768.     \ifdim \!dimenA>\!plotheadingoffset
  769.       \!plotheadingoffset=\!dimenA % ** Greatest excess over the plot area
  770.     \fi
  771.   \fi}
  772. % ** \grid {c} {r} 
  773. % ** Partitions the plot area into c columns and r rows; see Subsection 3.3
  774. % ** of the manual.
  775. % ** (Other grid patterns can be drawn with the TICKS option of the \axis 
  776. % ** command.
  777. \def\grid #1 #2 {%
  778.   \!countA=#1\advance\!countA 1
  779.   \axis bottom invisible ticks length <\!zpt> andacross quantity {\!countA} /
  780.   \!countA=#2\advance\!countA 1
  781.   \axis left   invisible ticks length <\!zpt> andacross quantity {\!countA} / }
  782. % ** \plotheading{HEADING}
  783. % ** Places HEADING centered above the top of the plotarea (and above
  784. % ** any top axis ticks marks, tick labels, and axis label); see
  785. % ** Subsection 3.3 of the manual.
  786. \def\plotheading#1 {%
  787.   \advance\!plotheadingoffset \headingtoplotskip
  788.   \!dimenput {#1} [B] <.5\!xaxislength,\!plotheadingoffset>
  789.     (\!arealloc,\!areatloc)}
  790. % ** From here on, the routines are internal.
  791. \def\!axisxsetup{%
  792.   \!axisxlevel=\!arealloc
  793.   \!axisstart=\!arealloc
  794.   \!axisend=\!arearloc
  795.   \!axisLength=\!xaxislength
  796.   \!!origin=\!xorigin
  797.   \!!unit=\!xunit
  798.   \!xswitchtrue
  799.   \if!axisvisible 
  800.     \!makeaxis
  801.   \fi}
  802. \def\!axisysetup{%
  803.   \!axisylevel=\!areabloc
  804.   \!axisstart=\!areabloc
  805.   \!axisend=\!areatloc
  806.   \!axisLength=\!yaxislength
  807.   \!!origin=\!yorigin
  808.   \!!unit=\!yunit
  809.   \!xswitchfalse
  810.   \if!axisvisible
  811.     \!makeaxis
  812.   \fi}
  813. \def\!makeaxis{%
  814.   \setbox\!boxA=\hbox{% (Make a pseudo-y[x] tick for an x[y]-axis)
  815.     \beginpicture
  816.       \!setdimenmode
  817.       \setcoordinatesystem point at {\!zpt} {\!zpt}   
  818.       \putrule from {\!zpt} {\!zpt} to
  819.         {\!tickysign\!tickysign\!axisLength} 
  820.         {\!tickxsign\!tickxsign\!axisLength}
  821.     \endpicturesave <\!Xsave,\!Ysave>}%
  822.     \wd\!boxA=\!zpt
  823.     \!placetick\!axisstart}
  824. \def\!placeaxislabel{%
  825.   \advance\!offset \valuestolabelleading
  826.   \if!xswitch
  827.     \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl]
  828.       <.5\!axisLength,\!tickysign\!offset> (\!axisxlevel,\!axisylevel)
  829.     \advance\!offset \!dp  % ** advance offset by the "tallness"
  830.     \advance\!offset \!ht  % ** of the label
  831.   \else
  832.     \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl]
  833.       <\!tickxsign\!offset,.5\!axisLength> (\!axisxlevel,\!axisylevel)
  834.   \fi
  835.   \!axisLaBeL={}}
  836. % *******************************
  837. % *** ARROWS  (Draws arrows)  ***
  838. % *******************************
  839. % ** User commands
  840. % **  \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION]
  841. % **    [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO
  842. % **  \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO
  843. % ** \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION]
  844. % **    [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO
  845. % ** Draws an arrow from (XFROM,YFROM) to (XTO,YTO).  The arrow head
  846. % ** is constructed two quadratic arcs, which extend back a distance
  847. % ** ARROW HEAD LENGTH (a dimension) on both sides of the arrow shaft.
  848. % ** All the way back the arcs are a distance BASE FRACTION*ARROW HEAD
  849. % ** LENGTH apart, while half-way back they are a distance MID FRACTION*
  850. % ** ARROW HEAD LENGTH apart. <XSHIFT,YSHIFT> is optional, and has
  851. % ** its usual interpreation. See Subsection 5.4 of the manual.
  852. \def\arrow <#1> [#2,#3]{%
  853.   \!ifnextchar<{\!arrow{#1}{#2}{#3}}{\!arrow{#1}{#2}{#3}<\!zpt,\!zpt> }}
  854. \def\!arrow#1#2#3<#4,#5> from #6 #7 to #8 #9 {%
  855. % ** convert to dimensions
  856.   \!xloc=\!M{#8}\!xunit   
  857.   \!yloc=\!M{#9}\!yunit
  858.   \!dxpos=\!xloc  \!dimenA=\!M{#6}\!xunit  \advance \!dxpos -\!dimenA
  859.   \!dypos=\!yloc  \!dimenA=\!M{#7}\!yunit  \advance \!dypos -\!dimenA
  860.   \let\!MAH=\!M%                         ** save current c/d mode
  861.   \!setdimenmode%                        ** go into dimension mode
  862.   \!xshift=#4\relax  \!yshift=#5\relax%  ** pick up shift
  863.   \!reverserotateonly\!xshift\!yshift%   ** back rotate shift
  864.   \advance\!xshift\!xloc  \advance\!yshift\!yloc
  865. % **  draw shaft of arrow
  866.   \!xS=-\!dxpos  \advance\!xS\!xshift
  867.   \!yS=-\!dypos  \advance\!yS\!yshift
  868.   \!start (\!xS,\!yS)
  869.   \!ljoin (\!xshift,\!yshift)
  870. % ** find 32*cosine and 32*sine of angle of rotation
  871.   \!Pythag\!dxpos\!dypos\!arclength
  872.   \!divide\!dxpos\!arclength\!dxpos  
  873.   \!dxpos=32\!dxpos  \!removept\!dxpos\!!cos
  874.   \!divide\!dypos\!arclength\!dypos  
  875.   \!dypos=32\!dypos  \!removept\!dypos\!!sin
  876. % ** construct arrowhead
  877.   \!halfhead{#1}{#2}{#3}%                ** draw half of arrow head
  878.   \!halfhead{#1}{-#2}{-#3}%              ** draw other half
  879.   \let\!M=\!MAH%                         ** restore old c/d mode
  880.   \ignorespaces}
  881. % ** draw half of arrow head
  882.   \def\!halfhead#1#2#3{%
  883.     \!dimenC=-#1%                
  884.     \divide \!dimenC 2 %                 ** half way back
  885.     \!dimenD=#2\!dimenC%                 ** half the mid width
  886.     \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xM,\!yM)
  887.     \!dimenC=-#1%                        ** all the way back
  888.     \!dimenD=#3\!dimenC
  889.     \!dimenD=.5\!dimenD%                 ** half the full width
  890.     \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xE,\!yE)
  891.     \!start (\!xshift,\!yshift)
  892.     \advance\!xM\!xshift  \advance\!yM\!yshift
  893.     \advance\!xE\!xshift  \advance\!yE\!yshift
  894.     \!qjoin (\!xM,\!yM) (\!xE,\!yE) 
  895.     \ignorespaces}
  896. % ** \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO
  897. % **   Makes things like <--- text --->, using arrow heads from TeX's fonts.
  898. % **   See Subsection 5.4 of the manual.
  899. \def\betweenarrows #1#2 from #3 #4 to #5 #6 {%
  900.   \!xloc=\!M{#3}\!xunit  \!xxloc=\!M{#5}\!xunit%   
  901.   \!yloc=\!M{#4}\!yunit  \!yyloc=\!M{#6}\!yunit%           
  902.   \!dxpos=\!xxloc  \advance\!dxpos by -\!xloc
  903.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  904.   \advance\!xloc .5\!dxpos
  905.   \advance\!yloc .5\!dypos
  906.   \let\!MBA=\!M%           ** save current coord\dimen mode
  907.   \!setdimenmode%          ** express locations in dimens
  908.   \ifdim\!dypos=\!zpt
  909.     \ifdim\!dxpos<\!zpt \!dxpos=-\!dxpos \fi
  910.     \put {\!lrarrows{\!dxpos}{#1}}#2{} at {\!xloc} {\!yloc}
  911.   \else
  912.     \ifdim\!dxpos=\!zpt
  913.       \ifdim\!dypos<\!zpt \!dypos=-\!zpt \fi
  914.       \put {\!udarrows{\!dypos}{#1}}#2{} at {\!xloc} {\!yloc}
  915.     \fi
  916.   \fi
  917.   \let\!M=\!MBA%           ** restore previous c/d mode
  918.   \ignorespaces}
  919. % ** Subroutine for left-right between arrows 
  920. \def\!lrarrows#1#2{% #1=width, #2=text
  921.   {\setbox\!boxA=\hbox{$\mkern-2mu\mathord-\mkern-2mu$}%
  922.    \setbox\!boxB=\hbox{$\leftarrow$}\!dimenE=\ht\!boxB
  923.    \setbox\!boxB=\hbox{}\ht\!boxB=2\!dimenE
  924.    \hbox to #1{$\mathord\leftarrow\mkern-6mu
  925.      \cleaders\copy\!boxA\hfil
  926.      \mkern-6mu\mathord-$%
  927.      \kern.4em $\vcenter{\box\!boxB}$$\vcenter{\hbox{#2}}$\kern.4em
  928.      $\mathord-\mkern-6mu
  929.      \cleaders\copy\!boxA\hfil
  930.      \mkern-6mu\mathord\rightarrow$}}}
  931. % ** Subroutine for up-down between arrows 
  932. \def\!udarrows#1#2{% #1=width, #2=text
  933.   {\setbox\!boxB=\hbox{#2}%
  934.    \setbox\!boxA=\hbox to \wd\!boxB{\hss$\vert$\hss}%
  935.    \!dimenE=\ht\!boxA \advance\!dimenE \dp\!boxA \divide\!dimenE 2
  936.    \vbox to #1{\offinterlineskip
  937.       \vskip .05556\!dimenE
  938.       \hbox to \wd\!boxB{\hss$\mkern.4mu\uparrow$\hss}\vskip-\!dimenE
  939.       \cleaders\copy\!boxA\vfil
  940.       \vskip-\!dimenE\copy\!boxA
  941.       \vskip\!dimenE\copy\!boxB\vskip.4em
  942.       \copy\!boxA\vskip-\!dimenE
  943.       \cleaders\copy\!boxA\vfil
  944.       \vskip-\!dimenE \hbox to \wd\!boxB{\hss$\mkern.4mu\downarrow$\hss}
  945.       \vskip .05556\!dimenE}}}
  946. % ***************************
  947. % *** BARS  (Draws bars)  ***
  948. % ***************************
  949. % ** User commands:
  950. % ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART
  951. % **   to XEND YEND
  952. % ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD
  953. % **   [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)]
  954. % **   [endlabels  ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)]
  955. % ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART
  956. % **   to XEND YEND
  957. % ** Either XSTART=XEND or YSTART=YEND. Draws a rectangle between
  958. % **   (XSTART,YSTART) & (XEND,YEND). The "depth" of the rectangle
  959. % **   is determined by those two plot positions; its other
  960. % **   dimension "breadth" is specified by the dimension BREADTH.
  961. % ** See Subsection 4.2 of the manual.
  962. \def\putbar#1breadth <#2> from #3 #4 to #5 #6 {%
  963.   \!xloc=\!M{#3}\!xunit  \!xxloc=\!M{#5}\!xunit%   
  964.   \!yloc=\!M{#4}\!yunit  \!yyloc=\!M{#6}\!yunit%           
  965.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  966.   \!dimenI=#2  
  967.   \ifdim \!dimenI=\!zpt %            ** If 0 breadth
  968.     \putrule#1from {#3} {#4} to {#5} {#6} % ** Then draw line
  969.   \else %                            ** Else, put in a rectangle
  970.     \let\!MBar=\!M%                  ** save current c/d mode
  971.     \!setdimenmode %                 ** go into dimension mode
  972.     \divide\!dimenI 2
  973.     \ifdim \!dypos=\!zpt             
  974.       \advance \!yloc -\!dimenI %    ** Equal y coordinates
  975.       \advance \!yyloc \!dimenI
  976.     \else
  977.       \advance \!xloc -\!dimenI %    ** Equal x coordinates
  978.       \advance \!xxloc \!dimenI
  979.     \fi
  980.     \putrectangle#1corners at {\!xloc} {\!yloc} and {\!xxloc} {\!yyloc}
  981.     \let\!M=\!MBar %                 ** restore c/d mode
  982.   \fi
  983.   \ignorespaces}
  984. % ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD
  985. % **   [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)]
  986. % **   [endlabels  ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)]
  987. % ** This command puts PiCTeX into the bar graph drawing mode described
  988. % **   in Subsection 4.4 of the manual.
  989. \def\setbars#1breadth <#2> baseline at #3 = #4 {%
  990.   \edef\!barshift{#1}%
  991.   \edef\!barbreadth{#2}%
  992.   \edef\!barorientation{#3}%
  993.   \edef\!barbaseline{#4}%
  994.   \def\!bardobaselabel{\!bardoendlabel}%
  995.   \def\!bardoendlabel{\!barfinish}%
  996.   \let\!drawcurve=\!barcurve
  997.   \!setbars}
  998. \def\!setbars{%
  999.   \futurelet\!nextchar\!!setbars}
  1000. \def\!!setbars{%
  1001.   \if b\!nextchar
  1002.     \def\!!!setbars{\!setbarsbget}%
  1003.   \else 
  1004.     \if e\!nextchar
  1005.       \def\!!!setbars{\!setbarseget}%
  1006.     \else
  1007.       \def\!!!setbars{\relax}%
  1008.     \fi
  1009.   \fi
  1010.   \!!!setbars}
  1011. \def\!setbarsbget baselabels (#1) {%
  1012.   \def\!barbaselabelorientation{#1}%
  1013.   \def\!bardobaselabel{\!!bardobaselabel}%
  1014.   \!setbars}
  1015. \def\!setbarseget endlabels (#1) {%
  1016.   \edef\!barendlabelorientation{#1}%
  1017.   \def\!bardoendlabel{\!!bardoendlabel}%
  1018.   \!setbars}
  1019. % ** \!barcurve
  1020. % ** Draws a bargraph with preset values of barshift, barbreadth,
  1021. % ** barorientation (x or y) and barbaseline (coordinate)
  1022. \def\!barcurve #1 #2 {%
  1023.   \if y\!barorientation
  1024.     \def\!basexarg{#1}%
  1025.     \def\!baseyarg{\!barbaseline}%
  1026.   \else
  1027.     \def\!basexarg{\!barbaseline}%
  1028.     \def\!baseyarg{#2}%
  1029.   \fi
  1030.   \expandafter\putbar\!barshift breadth <\!barbreadth> from {\!basexarg}
  1031.     {\!baseyarg} to {#1} {#2}
  1032.   \def\!endxarg{#1}%
  1033.   \def\!endyarg{#2}%
  1034.   \!bardobaselabel}
  1035. \def\!!bardobaselabel "#1" {%
  1036.   \put {#1}\!barbaselabelorientation{} at {\!basexarg} {\!baseyarg}
  1037.   \!bardoendlabel}
  1038. \def\!!bardoendlabel "#1" {%
  1039.   \put {#1}\!barendlabelorientation{} at {\!endxarg} {\!endyarg}
  1040.   \!barfinish}
  1041. \def\!barfinish{%
  1042.   \!ifnextchar/{\!finish}{\!barcurve}}
  1043. % ********************************
  1044. % *** BOXES (Draws rectangles) ***
  1045. % ********************************
  1046. % ** User commands:
  1047. % **   \putrectangle [<XSHIFT,YSHIFT>] corners at  XCOORD1 YCOORD1
  1048. % **     and  XCOORD2 YCOORD2 
  1049. % **   \shaderectangleson
  1050. % **   \shaderectanglesoff
  1051. % **   \frame [<SEPARATION>] {TEXT}
  1052. % **   \rectangle <WIDTH> <HEIGHT>
  1053. % **  \putrectangle [<XSHIFT,YSHIFT>] corners at XCOORD1 YCOORD1 
  1054. % **    and  XCOORD2 YCOORD2 
  1055. % **  Draws a rectangle with corners at (X1,Y1), (X2,Y1), (X1,Y2), (X2,Y2)
  1056. % **  Lines have thickness \linethickness, and overlap at the corners.
  1057. % **  The optional field  <XSHIFT,YSHIFT>  functions as with a \put command.
  1058. % **  See Subsection 4.2 of the manual.
  1059. \def\putrectangle{%
  1060.   \!ifnextchar<{\!putrectangle}{\!putrectangle<\!zpt,\!zpt> }}
  1061. \def\!putrectangle<#1,#2> corners at #3 #4 and #5 #6 {%
  1062. % ** get locations
  1063.   \!xone=\!M{#3}\!xunit  \!xtwo=\!M{#5}\!xunit%   
  1064.   \!yone=\!M{#4}\!yunit  \!ytwo=\!M{#6}\!yunit%           
  1065.   \ifdim \!xtwo<\!xone
  1066.     \!dimenI=\!xone  \!xone=\!xtwo  \!xtwo=\!dimenI
  1067.   \fi
  1068.   \ifdim \!ytwo<\!yone
  1069.     \!dimenI=\!yone  \!yone=\!ytwo  \!ytwo=\!dimenI
  1070.   \fi
  1071.   \!dimenI=#1\relax  \advance\!xone\!dimenI  \advance\!xtwo\!dimenI
  1072.   \!dimenI=#2\relax  \advance\!yone\!dimenI  \advance\!ytwo\!dimenI
  1073.   \let\!MRect=\!M%                  ** save current coord/dimen mode
  1074.   \!setdimenmode
  1075. % ** shade rectangle if appropriate
  1076.   \!shaderectangle
  1077. % ** draw horizontal edges
  1078.   \!dimenI=.5\linethickness
  1079.   \advance \!xone  -\!dimenI%       ** adjust x-location to overlap corners
  1080.   \advance \!xtwo   \!dimenI%       ** ditto
  1081.   \putrule from {\!xone} {\!yone} to {\!xtwo} {\!yone} 
  1082.   \putrule from {\!xone} {\!ytwo} to {\!xtwo} {\!ytwo} 
  1083. % ** draw vertical edges
  1084.   \advance \!xone   \!dimenI%       ** restore original x-values
  1085.   \advance \!xtwo  -\!dimenI% 
  1086.   \advance \!yone  -\!dimenI%       ** adjust y-location to overlap corners
  1087.   \advance \!ytwo   \!dimenI%       ** ditto
  1088.   \putrule from {\!xone} {\!yone} to {\!xone} {\!ytwo} 
  1089.   \putrule from {\!xtwo} {\!yone} to {\!xtwo} {\!ytwo} 
  1090.   \let\!M=\!MRect%                  ** restore coord/dimen mode
  1091.   \ignorespaces}
  1092. % ** \shaderectangleson 
  1093. % **   Subsequent rectangles will be shaded according to 
  1094. % **   the current shading pattern.  Affects \putrectangle, \putbar,
  1095. % **   \frame, \sethistograms, and \setbars. See Subsection 7.5 of the manual.
  1096. \def\shaderectangleson{%     
  1097.   \def\!shaderectangle{\!!shaderectangle}%
  1098.   \ignorespaces}
  1099. % ** \shaderectanglesoff 
  1100. % **    Suppresses  \shaderectangleson.  The default.
  1101. \def\shaderectanglesoff{%
  1102.   \def\!shaderectangle{}%
  1103.   \ignorespaces}
  1104. \shaderectanglesoff
  1105. % ** The following internal routine shades the current rectangle, when
  1106. % **   \!shaderectangle = \!!shaderectangle . 
  1107. \def\!!shaderectangle{%
  1108.   \!dimenA=\!xtwo  \advance \!dimenA -\!xone
  1109.   \!dimenB=\!ytwo  \advance \!dimenB -\!yone
  1110.   \ifdim \!dimenA<\!dimenB
  1111.     \!startvshade (\!xone,\!yone,\!ytwo)
  1112.     \!lshade      (\!xtwo,\!yone,\!ytwo)
  1113.   \else
  1114.     \!starthshade (\!yone,\!xone,\!xtwo)
  1115.     \!lshade      (\!ytwo,\!xone,\!xtwo)
  1116.   \fi
  1117.   \ignorespaces}
  1118. % ** \frame [<SEPARATION>] {TEXT}
  1119. % ** Draws a frame of thickness linethickness about the box enclosing
  1120. % **   TEXT; the frame is separated from the box by a distance of
  1121. % **   SEPARATION.  The result is an hbox with the same baseline as TEXT.
  1122. % **   If <SEPARATION> is omitted, you get the effect of <0pt>.
  1123. % ** See Subsection 4.2 of the manual.
  1124. \def\frame{%
  1125.   \!ifnextchar<{\!frame}{\!frame<\!zpt> }}
  1126. \long\def\!frame<#1> #2{%
  1127.   \beginpicture
  1128.     \setcoordinatesystem units <1pt,1pt> point at 0 0 
  1129.     \put {#2} [Bl] at 0 0 
  1130.     \!dimenA=#1\relax
  1131.     \!dimenB=\!wd \advance \!dimenB \!dimenA
  1132.     \!dimenC=\!ht \advance \!dimenC \!dimenA
  1133.     \!dimenD=\!dp \advance \!dimenD \!dimenA
  1134.     \let\!MFr=\!M
  1135.     \!setdimenmode
  1136.     \putrectangle corners at {-\!dimenA} {-\!dimenD} and {\!dimenB} {\!dimenC}
  1137.     \!setcoordmode
  1138.     \let\!M=\!MFr
  1139.   \endpicture
  1140.   \ignorespaces}
  1141. % ** \rectangle <WIDTH> <HEIGHT>
  1142. % ** Constructs a rectangle of width WIDTH and heigth HEIGHT. 
  1143. % ** See Subsection 4.2 of the manual.
  1144. \def\rectangle <#1> <#2> {%
  1145.   \setbox0=\hbox{}\wd0=#1\ht0=#2\frame {\box0}}
  1146. % *********************************************
  1147. % ***  CURVES  (Upper level \plot commands) ***
  1148. % *********************************************
  1149. % ** User commands
  1150. % **   \plot  DATA  /
  1151. % **   \plot  "FILE NAME"
  1152. % **   \setquadratic
  1153. % **   \setlinear
  1154. % **   \sethistograms
  1155. % **   \vshade  ...
  1156. % **   \hshade  ...
  1157. % \plot: multi-purpose command. Draws histograms, bar graphs, piecewise-linear
  1158. % or piecewise quadratic curves, depending on the setting of \!drawcurve.
  1159. % See Subsections 4.3-4.5, 5.1, 5.2 of the manual.
  1160. \def\plot{%
  1161.   \!ifnextchar"{\!plotfromfile}{\!drawcurve}}
  1162. \def\!plotfromfile"#1"{%
  1163.   \expandafter\!drawcurve \input #1 /}
  1164. % Command to set piecewise quadratic mode
  1165. % See Subsections 5.1, 7.3, and 7.4 of the manual.
  1166. \def\setquadratic{%
  1167.   \let\!drawcurve=\!qcurve
  1168.   \let\!!Shade=\!!qShade
  1169.   \let\!!!Shade=\!!!qShade}
  1170. % Command to set piecewise linear mode
  1171. % See Subsections 5.1, 7.3, and 7.4 of the manual.
  1172. \def\setlinear{%
  1173.   \let\!drawcurve=\!lcurve
  1174.   \let\!!Shade=\!!lShade
  1175.   \let\!!!Shade=\!!!lShade}
  1176. % Command to set histogram mode
  1177. % See Subsection 4.3 of the manual.
  1178. \def\sethistograms{%
  1179.   \let\!drawcurve=\!hcurve}
  1180. % Commands to cycle through list of coordinates in piecewise quadratic 
  1181. % interpolation mode
  1182. \def\!qcurve #1 #2 {%
  1183.   \!start (#1,#2)
  1184.   \!Qjoin}
  1185. \def\!Qjoin#1 #2 #3 #4 {%
  1186.   \!qjoin (#1,#2) (#3,#4)             % \!qjoin  is defined in QUADRATIC
  1187.   \!ifnextchar/{\!finish}{\!Qjoin}}
  1188. % Commands to cycle through list of coordinates in piecewise linear 
  1189. % interpolation mode
  1190. \def\!lcurve #1 #2 {%
  1191.   \!start (#1,#2)
  1192.   \!Ljoin}
  1193. \def\!Ljoin#1 #2 {%
  1194.   \!ljoin (#1,#2)                    % \!ljoin  is defined in LINEAR
  1195.   \!ifnextchar/{\!finish}{\!Ljoin}}
  1196. \def\!finish/{\ignorespaces}
  1197. % Command to cycle through list of coordinates in histogram mode
  1198. \def\!hcurve #1 #2 {%
  1199.   \edef\!hxS{#1}%
  1200.   \edef\!hyS{#2}%
  1201.   \!hjoin}
  1202. \def\!hjoin#1 #2 {%
  1203.   \putrectangle corners at {\!hxS} {\!hyS} and {#1} {#2}
  1204.   \edef\!hxS{#1}%
  1205.   \!ifnextchar/{\!finish}{\!hjoin}}
  1206. % \vshade: See Subsection 7.3 of the manual.
  1207. \def\vshade #1 #2 #3 {%
  1208.   \!startvshade (#1,#2,#3)
  1209.   \!Shadewhat}
  1210. % \hshade: See Subsection 7.4 of the manual.
  1211. \def\hshade #1 #2 #3 {%
  1212.   \!starthshade (#1,#2,#3)
  1213.   \!Shadewhat}
  1214. % Commands to cycle through coordinates and optional "edge effect"
  1215. % fields while shading.
  1216. \def\!Shadewhat{%
  1217.   \futurelet\!nextchar\!Shade}
  1218. \def\!Shade{%
  1219.   \if <\!nextchar
  1220.     \def\!nextShade{\!!Shade}%
  1221.   \else
  1222.     \if /\!nextchar
  1223.       \def\!nextShade{\!finish}%
  1224.     \else
  1225.       \def\!nextShade{\!!!Shade}%
  1226.     \fi
  1227.   \fi
  1228.   \!nextShade}
  1229. \def\!!lShade<#1> #2 #3 #4 {%
  1230.   \!lshade <#1> (#2,#3,#4)                 % \!lshade is defined in SHADING
  1231.   \!Shadewhat}
  1232. \def\!!!lShade#1 #2 #3 {%
  1233.   \!lshade (#1,#2,#3)
  1234.   \!Shadewhat} 
  1235. \def\!!qShade<#1> #2 #3 #4 #5 #6 #7 {%
  1236.   \!qshade <#1> (#2,#3,#4) (#5,#6,#7)      % \!qshade is defined in SHADING
  1237.   \!Shadewhat}
  1238. \def\!!!qShade#1 #2 #3 #4 #5 #6 {%
  1239.   \!qshade (#1,#2,#3) (#4,#5,#6)
  1240.   \!Shadewhat} 
  1241. % ** Set default interpolation mode
  1242. \setlinear
  1243. %  ********************************************
  1244. %  *** DASHPATTERNS (Sets up dash patterns) ***
  1245. %  ********************************************
  1246. %  **  User commands:
  1247. %  **    \setdashpattern <DIMEN1,DIMEN2,DIMEN3,...>
  1248. %  **    \setdots <INTRADOT_DISTANCE>
  1249. %  **    \setdotsnear <INTRADOT_DISTANCE> for <ARC LENGTH>
  1250. %  **    \setdashes <DASH/SKIP_DISTANCE>
  1251. %  **    \setdashesnear <DASH/SKIP_DISTANCE> for <ARC LENGTH>
  1252. %  **    \setsolid
  1253. %  **    \findlength {CURVE CMDS}
  1254. %  **  Internal commands:
  1255. %  **    \!dashingon
  1256. %  **    \!dashingoff
  1257. %  **  Dash patterns are specified by a balanced token list whose complete
  1258. %  **    expansion has the form: DIMEN1,DIMEN2,DIMEN3,DIMEN4,... ; this produces
  1259. %  **    an arc of length DIMEN1, a skip of length DIMEN2, an arc of length
  1260. %  **    DIMEN3, a skip of length DIMEN4, ... .  Any number of DIMEN values may
  1261. %  **    be given. The pattern is repeated as many times (perhaps fractional)
  1262. %  **    as necessary to draw the curve. 
  1263. %  **  A dash pattern remains in effect until it is overridden by a call to
  1264. %  **    \setdashpattern, or to \setdots, \setdotsnear ... , \setdashes, 
  1265. %  **    \setdashesnear ... , or \setsolid.
  1266. %  **  Solid lines are the default.
  1267. %  **  \def\setdashpattern <DIMEN1,DIMEN2,DIMEN3,...>
  1268. %  **  The following routine converts a balanced list of tokens whose
  1269. %  **  complete expansion has the form  DIMEN1,DIMEN2, ... , DIMENk  into 
  1270. %  **  three list macros that are used in drawing dashed rules and curves:
  1271. %  **    !Flist:   \!Rule{DIMEN1}\!Skip{DIMEN2}\!Rule{DIMEN3}\!Skip{DIMEN4} ...
  1272. %  **    !Blist:   ...\!Skip{DIMEN4}\!Rule{DIMEN3}\!Skip{DIMEN2}\!Rule{DIMEN1}
  1273. %  **    !UDlist:  \\{DIMEN1}\\{DIMEN2}\\{DIMEN3}\\{DIMEN4} ...;
  1274. %  **  calculates \!leaderlength := DIMEN1 + ... + DIMENk; and
  1275. %  **  sets the curve drawing routines to dash mode.
  1276. %  **  Those lists are used by the curve drawing routines.
  1277. %  **  Dimenj ... may be given as an explicit dimension (e.g., 5pt), or
  1278. %  **  as an expression involving a dimension register (e.g., -2.5\dimen0).
  1279. %  **  See Subsection 6.2 of the manual
  1280. \def\setdashpattern <#1>{%
  1281.   \def\!Flist{}\def\!Blist{}\def\!UDlist{}%
  1282.   \!countA=0
  1283.   \!ecfor\!item:=#1\do{%
  1284.     \!dimenA=\!item\relax
  1285.     \expandafter\!rightappend\the\!dimenA\withCS{\\}\to\!UDlist%
  1286.     \advance\!countA  1
  1287.     \ifodd\!countA
  1288.       \expandafter\!rightappend\the\!dimenA\withCS{\!Rule}\to\!Flist%
  1289.       \expandafter\!leftappend\the\!dimenA\withCS{\!Rule}\to\!Blist%
  1290.     \else 
  1291.       \expandafter\!rightappend\the\!dimenA\withCS{\!Skip}\to\!Flist%
  1292.       \expandafter\!leftappend\the\!dimenA\withCS{\!Skip}\to\!Blist%
  1293.     \fi}%
  1294.   \!leaderlength=\!zpt
  1295.   \def\!Rule##1{\advance\!leaderlength  ##1}%
  1296.   \def\!Skip##1{\advance\!leaderlength  ##1}%
  1297.   \!Flist%
  1298.   \ifdim\!leaderlength>\!zpt 
  1299.   \else
  1300.     \def\!Flist{\!Skip{24in}}\def\!Blist{\!Skip{24in}}\ignorespaces
  1301.     \def\!UDlist{\\{\!zpt}\\{24in}}\ignorespaces
  1302.     \!leaderlength=24in
  1303.   \fi
  1304.   \!dashingon}   
  1305. %  **  \!dashingon  -- puts the curve drawing routines into dash mode
  1306. %  **  \!dashingoff -- puts the curve drawing routines into solid mode
  1307. %  **  These are internal commands, invoked by \setdashpattern and \setsolid
  1308. \def\!dashingon{%
  1309.   \def\!advancedashing{\!!advancedashing}%
  1310.   \def\!drawlinearsegment{\!lineardashed}%
  1311.   \def\!puthline{\!putdashedhline}%
  1312.   \def\!putvline{\!putdashedvline}%
  1313. %  \def\!putsline{\!putdashedsline}%
  1314.   \ignorespaces}% 
  1315. \def\!dashingoff{%
  1316.   \def\!advancedashing{\relax}%
  1317.   \def\!drawlinearsegment{\!linearsolid}%
  1318.   \def\!puthline{\!putsolidhline}%
  1319.   \def\!putvline{\!putsolidvline}%
  1320. %  \def\!putsline{\!putsolidsline}%
  1321.   \ignorespaces}
  1322. %  **  \setdots <LENGTH>  --  sets up a dot/skip pattern where dot (actually
  1323. %  **    the current plotsymbol) is plunked down once for every LENGTH 
  1324. %  **    traveled along the curve.  LENGTH defaults to 5pt.
  1325. %  **    See Subsection 6.1 of the manual.
  1326. \def\setdots{%
  1327.   \!ifnextchar<{\!setdots}{\!setdots<5pt>}}
  1328. \def\!setdots<#1>{%
  1329.   \!dimenB=#1\advance\!dimenB -\plotsymbolspacing
  1330.   \ifdim\!dimenB<\!zpt
  1331.     \!dimenB=\!zpt
  1332.   \fi
  1333. \setdashpattern <\plotsymbolspacing,\!dimenB>}
  1334. % ** \setdotsnear <LENGTH> for <ARC LENGTH>
  1335. % ** sets up a dot pattern where the dots are approximately LENGTH apart,
  1336. % ** the total length of the pattern is ARC LENGTH, and the pattern
  1337. % ** begins and ends with a dot. See Subsection 6.3 of the manual.
  1338. \def\setdotsnear <#1> for <#2>{%
  1339.   \!dimenB=#2\relax  \advance\!dimenB -.05pt  
  1340.   \!dimenC=#1\relax  \!countA=\!dimenC 
  1341.   \!dimenD=\!dimenB  \advance\!dimenD .5\!dimenC  \!countB=\!dimenD
  1342.   \divide \!countB  \!countA
  1343.   \ifnum 1>\!countB 
  1344.     \!countB=1
  1345.   \fi
  1346.   \divide\!dimenB  \!countB
  1347.   \setdots <\!dimenB>}
  1348. %  **  \setdashes <LENGTH>  --  sets up a dash/skip pattern where the dash
  1349. %  **    and the skip are each of length LENGTH (the dash is formed by
  1350. %  **    plunking down the current plotsymbol over an arc of length LENGTH
  1351. %  **    and so may actually be longer than LENGTH.  LENGTH defaults to 5pt.
  1352. %  **    See Subsection 6.1 of the manual.
  1353. \def\setdashes{%
  1354.   \!ifnextchar<{\!setdashes}{\!setdashes<5pt>}}
  1355. \def\!setdashes<#1>{\setdashpattern <#1,#1>}
  1356. % ** \setdashesnear ...
  1357. % ** Like \setdotsnear; the pattern begins and ends with a dash.
  1358. % ** See Subsection 6.3 of the manual.
  1359. \def\setdashesnear <#1> for <#2>{%
  1360.   \!dimenB=#2\relax  
  1361.   \!dimenC=#1\relax  \!countA=\!dimenC 
  1362.   \!dimenD=\!dimenB  \advance\!dimenD .5\!dimenC  \!countB=\!dimenD
  1363.   \divide \!countB  \!countA
  1364.   \ifodd \!countB 
  1365.   \else 
  1366.     \advance \!countB  1
  1367.   \fi
  1368.   \divide\!dimenB  \!countB
  1369.   \setdashes <\!dimenB>}
  1370. %  **  \setsolid  --  puts the curve drawing routines in "solid line" mode,
  1371. %  **    the default mode.  See Subsection 6.1 of the manual.
  1372. \def\setsolid{%
  1373.   \def\!Flist{\!Rule{24in}}\def\!Blist{\!Rule{24in}}%  
  1374.   \def\!UDlist{\\{24in}\\{\!zpt}}%
  1375.   \!dashingoff}  
  1376. \setsolid
  1377. %  **  \findlength {CURVE CMDS}
  1378. %  **  PiCTeX executes the \start, \ljoin, and \qjoin cmds comprising
  1379. %  **  CURVE CMDS without plotting anything, but stashes the length
  1380. %  **  of the phantom curve away in \totalarclength.
  1381. %  **  See Subsection 6.3 of the manual.
  1382. \def\findlength#1{%
  1383.   \begingroup
  1384.     \setdashpattern <0pt, \maxdimen>
  1385.     \setplotsymbol ({})  
  1386.     \dontsavelinesandcurves
  1387.     #1%
  1388.   \endgroup
  1389.   \ignorespaces}
  1390. % *************************************************************
  1391. % *** DIVISION  (Does long division of dimension registers) ***
  1392. % *************************************************************
  1393. % ** User command:
  1394. % **   \Divide {DIVIDEND} by {DIVISOR} forming {RESULT}
  1395. % ** Internal command
  1396. % **   \!divide{DIVIDEND}{DIVISOR}{RESULT}
  1397. % **  \!divide DIVIDEND [by] DIVISOR [to get] ANSWER
  1398. % **  Divides the dimension DIVIDEND by the dimension DIVISOR, placing the 
  1399. % **  quotient in the dimension register ANSWER.  Values are understood to 
  1400. % **  be in points.  E.g.  12.5pt/1.4pt=8.92857pt.
  1401. % **  Quotient is accurate to 1/65536pt=2**[-16]pt
  1402. % **  |DIVISOR| should be < 2048pt (about 28 inches).
  1403. \def\!divide#1#2#3{%
  1404.   \!dimenB=#1%                      **  dimB  holds current remainder (r)
  1405.   \!dimenC=#2%                      **  dimC  holds divisor (d)
  1406.   \!dimenD=\!dimenB%                **  dimD  holds quotient q=r/d for this 
  1407.   \divide \!dimenD \!dimenC%        **    step, in units of scaled pts
  1408.   \!dimenA=\!dimenD%                **  dimA  eventually holds answer (a)
  1409.   \multiply\!dimenD \!dimenC%       **  r <-- r - dq
  1410.   \advance\!dimenB -\!dimenD%       **  First step complete. Have integer part
  1411. %                                   **  of a, and corresponding remainder.
  1412.   \!dimenD=\!dimenC%                **  Temporarily use dimD to hold |d|
  1413.     \ifdim\!dimenD<\!zpt \!dimenD=-\!dimenD 
  1414.   \fi
  1415.   \ifdim\!dimenD<64pt%              **  Branch on the magnitude of |d|
  1416.     \!divstep[\!tfs]\!divstep[\!tfs]%
  1417.   \else 
  1418.     \!!divide
  1419.   \fi
  1420.   #3=\!dimenA\ignorespaces}
  1421. % **  The following code handles divisors  d  with 
  1422. % **    (1)  .88in =  64pt <= d <  256pt =  3.54in
  1423. % **    (2) 3.54in = 256pt <= d < 2048pt = 28.34in
  1424. % **  Anything bigger than that may result in an overflow condition.
  1425. % **  For our purposes, we should never even see case (2).
  1426. \def\!!divide{%
  1427.   \ifdim\!dimenD<256pt
  1428.     \!divstep[64]\!divstep[32]\!divstep[32]%
  1429.   \else 
  1430.     \!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]%
  1431.     \!dimenA=2\!dimenA
  1432.   \fi}
  1433. % **  The following macro does the real long division work.
  1434. \def\!divstep[#1]{%                 **  #1 = "B"
  1435.   \!dimenB=#1\!dimenB%              **  r <-- B*r
  1436.   \!dimenD=\!dimenB%                **  dimD  holds quotient q=r/d for this 
  1437.     \divide \!dimenD by \!dimenC%   **    step, in units of scaled pts
  1438.   \!dimenA=#1\!dimenA%              **  a <-- B*a + q
  1439.     \advance\!dimenA by \!dimenD%
  1440.   \multiply\!dimenD by \!dimenC%    **  r <-- r - dq
  1441.     \advance\!dimenB by -\!dimenD}
  1442. % **  \Divide:  See Subsection 9.3 of the manual.
  1443. \def\Divide <#1> by <#2> forming <#3> {%
  1444.   \!divide{#1}{#2}{#3}}
  1445. % *********************************************
  1446. % *** ELLIPSES (Draws ellipses and circles) ***
  1447. % *********************************************
  1448. % ** User commands
  1449. % **   \ellipticalarc  axes ratio A:B  DEGREES degrees from XSTART YSTART 
  1450. % **      center at XCENTER YCENTER 
  1451. % **   \circulararc DEGREES degrees from XSTART YSTART 
  1452. % **      center at XCENTER YCENTER 
  1453. % ** Internal command
  1454. % **   \!sinandcos{32*ANGLE in radians}{32*SIN}{32*COS}
  1455. % **   \ellipticalarc  axes ratio A:B  DEGREES degrees from XSTART YSTART 
  1456. % **      center at XCENTER YCENTER 
  1457. % **    Draws a elliptical arc starting at the coordinate point (XSTART,YSTART).
  1458. % **    The center of the ellipse of which the arc is a segment is at 
  1459. % **      (XCENTER,YCENTER).
  1460. % **    The arc extends through an angle of DEGREES degrees (may be + or -).
  1461. % **    A:B is the ratio of the length of the xaxis to the length of
  1462. % **      the yaxis of the ellipse
  1463. % **    Sqrt{[(XSTART-XCENTER)/A]**2 + [(YSTART-YCENTER)/B]**2}
  1464. % **      must be < 512pt (about 7in).
  1465. % **    Doesn't modify the dimensions (ht, dp, wd) of the PiCture under
  1466. % **      construction.
  1467. % ** \circulararc  --  See Subsection 5.3 of the manual.
  1468. \def\circulararc{%
  1469.   \ellipticalarc axes ratio 1:1 }
  1470. % ** \ellipticalarc  --  See Subsection 5.3 of the manual.
  1471. \def\ellipticalarc axes ratio #1:#2 #3 degrees from #4 #5 center at #6 #7 {%
  1472.   \!angle=#3pt\relax%                    ** get angle
  1473.   \ifdim\!angle>\!zpt 
  1474.     \def\!sign{}%                        ** counterclockwise
  1475.   \else 
  1476.     \def\!sign{-}\!angle=-\!angle%       ** clockwise
  1477.   \fi
  1478.   \!xxloc=\!M{#6}\!xunit%                ** convert CENTER to dimension
  1479.   \!yyloc=\!M{#7}\!yunit     
  1480.   \!xxS=\!M{#4}\!xunit%                  ** get STARTing point on rim of ellipse
  1481.   \!yyS=\!M{#5}\!yunit
  1482.   \advance\!xxS -\!xxloc%                ** make center of ellipse (0,0)
  1483.   \advance\!yyS -\!yyloc
  1484.   \!divide\!xxS{#1pt}\!xxS %             ** scale point on ellipse to point on 
  1485.   \!divide\!yyS{#2pt}\!yyS %                 corresponding circle
  1486.   \let\!MC=\!M%                          ** save current c/d mode
  1487.   \!setdimenmode%                        ** go into dimension mode
  1488.   \!xS=#1\!xxS  \advance\!xS\!xxloc
  1489.   \!yS=#2\!yyS  \advance\!yS\!yyloc
  1490.   \!start (\!xS,\!yS)%
  1491.   \!loop\ifdim\!angle>14.9999pt%         ** draw in major portion of ellipse 
  1492.     \!rotate(\!xxS,\!yyS)by(\!cos,\!sign\!sin)to(\!xxM,\!yyM) 
  1493.     \!rotate(\!xxM,\!yyM)by(\!cos,\!sign\!sin)to(\!xxE,\!yyE)
  1494.     \!xM=#1\!xxM  \advance\!xM\!xxloc  \!yM=#2\!yyM  \advance\!yM\!yyloc
  1495.     \!xE=#1\!xxE  \advance\!xE\!xxloc  \!yE=#2\!yyE  \advance\!yE\!yyloc
  1496.     \!qjoin (\!xM,\!yM) (\!xE,\!yE)
  1497.     \!xxS=\!xxE  \!yyS=\!yyE 
  1498.     \advance \!angle -15pt
  1499.   \repeat
  1500.   \ifdim\!angle>\!zpt%                   ** complete remaining arc, if any
  1501.     \!angle=100.53096\!angle%            ** convert angle to radians, divide
  1502.     \divide \!angle 360 %                **   by 2, and multiply by 32
  1503.     \!sinandcos\!angle\!!sin\!!cos%      ** get 32*sin & 32*cos
  1504.     \!rotate(\!xxS,\!yyS)by(\!!cos,\!sign\!!sin)to(\!xxM,\!yyM) 
  1505.     \!rotate(\!xxM,\!yyM)by(\!!cos,\!sign\!!sin)to(\!xxE,\!yyE)
  1506.     \!xM=#1\!xxM  \advance\!xM\!xxloc  \!yM=#2\!yyM  \advance\!yM\!yyloc
  1507.     \!xE=#1\!xxE  \advance\!xE\!xxloc  \!yE=#2\!yyE  \advance\!yE\!yyloc
  1508.     \!qjoin (\!xM,\!yM) (\!xE,\!yE)
  1509.   \fi
  1510.   \let\!M=\!MC%                          ** restore c/d mode
  1511.   \ignorespaces}%                        **   if appropriate
  1512. %  ** \!rotate(XREG,YREG)by(32cos,32sin)to(XXREG,YYREG)
  1513. %  ** rotates (XREG,YREG) by angle with specfied scaled cos & sin to
  1514. %  ** (XXREG,YYREG).  Uses \!dimenA & \!dimenB as scratch registers.
  1515. \def\!rotate(#1,#2)by(#3,#4)to(#5,#6){% 
  1516.   \!dimenA=#3#1\advance \!dimenA -#4#2%   ** Rcos(x+t)=Rcosx*cost - Rsinx*sint
  1517.   \!dimenB=#3#2\advance \!dimenB  #4#1%   ** Rsin(x+t)=Rsinx*cost + Rcosx*sint
  1518.   \divide \!dimenA 32  \divide \!dimenB 32 
  1519.   #5=\!dimenA  #6=\!dimenB
  1520.   \ignorespaces}
  1521. \def\!sin{4.17684}%                       ** 32*sin(pi/24) (pi/24=7.5deg)
  1522. \def\!cos{31.72624}%                      ** 32*cos(pi/24)
  1523. %  ** \!sinandcos{32*ANGLE in radians}{\SINCS}{\COSCS}
  1524. %  **   Computes the 32*sine and 32*cosine of a small ANGLE expressed in 
  1525. %  **   radians/32 and puts these values in the replacement texts of 
  1526. %  **   \SINCS and \COSCS
  1527. \def\!sinandcos#1#2#3{%
  1528.  \!dimenD=#1%                **  angle is expressed in radians/32: 1pt = 1/32rad
  1529.  \!dimenA=\!dimenD%          **  dimA will eventually contain 32sin(angle)in pts
  1530.  \!dimenB=32pt%              **  dimB will eventually contain 32cos(angle)in pts
  1531.  \!removept\!dimenD\!value%  **  get value of 32*angle, without "pt"
  1532.  \!dimenC=\!dimenD%          **  holds 32*angle**i/i! in pts
  1533.  \!dimenC=\!value\!dimenC \divide\!dimenC by 64 %   ** now 32*angle**2/2
  1534.  \advance\!dimenB by -\!dimenC%                     ** 32-32*angle**2/2
  1535.  \!dimenC=\!value\!dimenC \divide\!dimenC by 96 %   ** now 32*angle**3/3!
  1536.  \advance\!dimenA by -\!dimenC%                     ** now 32*(angle-angle**3/6)
  1537.  \!dimenC=\!value\!dimenC \divide\!dimenC by 128 %  ** now 32*angle**4/4!
  1538.  \advance\!dimenB by \!dimenC%
  1539.  \!removept\!dimenA#2%                              ** set 32*sin(angle)
  1540.  \!removept\!dimenB#3%                              ** set 32*cos(angle)
  1541.  \ignorespaces}
  1542. % *****************************************************************
  1543. % ***  RULES  (Draws rules, i.e., horizontal & vertical lines)  ***
  1544. % *****************************************************************
  1545. % **  User command:
  1546. % **    \putrule [<XDIMEN,YDIMEN>] from  XCOORD1 YCOORD1 
  1547. % **      to  XCOORD2 YCOORD2 
  1548. % **  Internal commands:
  1549. % **    \!puthline [<XDIMEN,YDIMEN>]    (h = horizontal)
  1550. % **      Set by dashpat to either: \!putsolidhline  or \!putdashedhline
  1551. % **    \!putvline [<XDIMEN,YDIMEN>]    (v = vertical)
  1552. % **      Either:  \!putsolidvline  or  \!putdashedvline
  1553. % **  \putrule [<XDIMEN,YDIMEN>] from XCOORD1 YCOORD1
  1554. % **    to XCOORD2 YCOORD2
  1555. % **  Draws a rule -- dashed or solid depending on the current dash pattern --
  1556. % **    from (X1,Y1) to (X2,Y2).  Uses TEK's  \hrule & \vrule & \leaders  
  1557. % **    constructions to handle horizontal & vertical lines efficiently both
  1558. % **    in terms of execution time and space in the DVI file.  
  1559. % **  See Subsection 4.1 of the manual.
  1560. \def\putrule#1from #2 #3 to #4 #5 {%
  1561.   \!xloc=\!M{#2}\!xunit  \!xxloc=\!M{#4}\!xunit%   
  1562.   \!yloc=\!M{#3}\!yunit  \!yyloc=\!M{#5}\!yunit%           
  1563.   \!dxpos=\!xxloc  \advance\!dxpos by -\!xloc
  1564.   \!dypos=\!yyloc  \advance\!dypos by -\!yloc
  1565.   \ifdim\!dypos=\!zpt
  1566.     \def\!!Line{\!puthline{#1}}\ignorespaces
  1567.   \else
  1568.     \ifdim\!dxpos=\!zpt
  1569.       \def\!!Line{\!putvline{#1}}\ignorespaces
  1570.     \else 
  1571.        \def\!!Line{}
  1572.     \fi
  1573.   \fi
  1574.   \let\!ML=\!M%           ** save current coord\dimen mode
  1575.   \!setdimenmode%         ** express locations in dimens
  1576.   \!!Line%
  1577.   \let\!M=\!ML%           ** restore previous c/d mode
  1578.   \ignorespaces}
  1579. % **  \!putsolidhline [<XDIMEN,YDIMEN>]
  1580. % **  Place horizontal solid line
  1581. \def\!putsolidhline#1{%
  1582.   \ifdim\!dxpos>\!zpt 
  1583.     \put{\!hline\!dxpos}#1[l] at {\!xloc} {\!yloc}
  1584.   \else 
  1585.     \put{\!hline{-\!dxpos}}#1[l] at {\!xxloc} {\!yyloc}
  1586.   \fi
  1587.   \ignorespaces}
  1588. % **  \!putsolidvline [shifted <XDIMEN,YDIMEN>]
  1589. % **  Place vertical solid line
  1590. \def\!putsolidvline#1{%
  1591.   \ifdim\!dypos>\!zpt 
  1592.     \put{\!vline\!dypos}#1[b] at {\!xloc} {\!yloc}
  1593.   \else 
  1594.     \put{\!vline{-\!dypos}}#1[b] at {\!xxloc} {\!yyloc}
  1595.   \fi
  1596.   \ignorespaces}
  1597. \def\!hline#1{\hbox to #1{\leaders \hrule height\linethickness\hfill}}
  1598. \def\!vline#1{\vbox to #1{\leaders \vrule width\linethickness\vfill}}
  1599. % **  \!putdashedhline [<XDIMEN,YDIMEN>]
  1600. % **  Place dashed horizontal line
  1601. \def\!putdashedhline#1{%
  1602.   \ifdim\!dxpos>\!zpt 
  1603.     \!DLsetup\!Flist\!dxpos
  1604.     \put{\hbox to \!totalleaderlength{\!hleaders}\!hpartialpattern\!Rtrunc}
  1605.       #1[l] at {\!xloc} {\!yloc} 
  1606.   \else 
  1607.     \!DLsetup\!Blist{-\!dxpos}
  1608.     \put{\!hpartialpattern\!Ltrunc\hbox to \!totalleaderlength{\!hleaders}}
  1609.       #1[r] at {\!xloc} {\!yloc} 
  1610.   \fi
  1611.   \ignorespaces}
  1612. % **  \!putdashedhline [<XDIMEN,YDIMEN>]
  1613. % **  Place dashed vertical line
  1614. \def\!putdashedvline#1{%
  1615.   \!dypos=-\!dypos%            ** vertical leaders go from top to bottom
  1616.   \ifdim\!dypos>\!zpt 
  1617.     \!DLsetup\!Flist\!dypos 
  1618.     \put{\vbox{\vbox to \!totalleaderlength{\!vleaders}
  1619.       \!vpartialpattern\!Rtrunc}}#1[t] at {\!xloc} {\!yloc} 
  1620.   \else 
  1621.     \!DLsetup\!Blist{-\!dypos}
  1622.     \put{\vbox{\!vpartialpattern\!Ltrunc
  1623.       \vbox to \!totalleaderlength{\!vleaders}}}#1[b] at {\!xloc} {\!yloc} 
  1624.   \fi
  1625.   \ignorespaces}
  1626. % **  The rest of the macros in this section are subroutines used by 
  1627. % **  \!putdashedhline and \!putdashedvline.
  1628. \def\!DLsetup#1#2{%            ** Dashed-Line set up
  1629.   \let\!RSlist=#1%             ** set !Rule-Skip list
  1630.   \!countB=#2%                 ** convert rule length to integer (number of sps)
  1631.   \!countA=\!leaderlength%     ** ditto, leaderlength
  1632.   \divide\!countB by \!countA% ** number of complete leader units
  1633.   \!totalleaderlength=\!countB\!leaderlength
  1634.   \!Rresiduallength=#2%
  1635.   \advance \!Rresiduallength by -\!totalleaderlength%  \** excess length
  1636.   \!Lresiduallength=\!leaderlength
  1637.   \advance \!Lresiduallength by -\!Rresiduallength
  1638.   \ignorespaces}
  1639. \def\!hleaders{%
  1640.   \def\!Rule##1{\vrule height\linethickness width##1}%
  1641.   \def\!Skip##1{\hskip##1}%
  1642.   \leaders\hbox{\!RSlist}\hfill}
  1643. \def\!hpartialpattern#1{%
  1644.   \!dimenA=\!zpt \!dimenB=\!zpt 
  1645.   \def\!Rule##1{#1{##1}\vrule height\linethickness width\!dimenD}%
  1646.   \def\!Skip##1{#1{##1}\hskip\!dimenD}%
  1647.   \!RSlist}
  1648. \def\!vleaders{%
  1649.   \def\!Rule##1{\hrule width\linethickness height##1}%
  1650.   \def\!Skip##1{\vskip##1}%
  1651.   \leaders\vbox{\!RSlist}\vfill}
  1652. \def\!vpartialpattern#1{%
  1653.   \!dimenA=\!zpt \!dimenB=\!zpt 
  1654.   \def\!Rule##1{#1{##1}\hrule width\linethickness height\!dimenD}%
  1655.   \def\!Skip##1{#1{##1}\vskip\!dimenD}%
  1656.   \!RSlist}
  1657. \def\!Rtrunc#1{\!trunc{#1}>\!Rresiduallength}
  1658. \def\!Ltrunc#1{\!trunc{#1}<\!Lresiduallength}
  1659. \def\!trunc#1#2#3{%          
  1660.   \!dimenA=\!dimenB         
  1661.   \advance\!dimenB by #1%
  1662.   \!dimenD=\!dimenB  \ifdim\!dimenD#2#3\!dimenD=#3\fi
  1663.   \!dimenC=\!dimenA  \ifdim\!dimenC#2#3\!dimenC=#3\fi
  1664.   \advance \!dimenD by -\!dimenC}
  1665. %  ****************************************************************
  1666. %  ***  LINEAR ARC  (Draws straight lines -- solid and dashed)  ***
  1667. %  ****************************************************************
  1668. %  **  User commands
  1669. %  **    \inboundscheckoff
  1670. %  **    \inboundscheckon
  1671. %  **  Internal commands 
  1672. %  **    \!start (XCOORD,YCOORD)
  1673. %  **    \!ljoin (XCOORD,YCOORD)
  1674. %  **    \!drawlinearsegment  --  set by \dashpat to either
  1675. %  **      \!linearsolid  or  \!lineardashed
  1676. %  **    \!advancedashing     --  set by \dashpat to either
  1677. %  **       \relax  or  \!!advancedashing
  1678. %  **    \!plotifinbounds     --  set by \inboundscheck off/on to either
  1679. %  **       \!plot  or  \!!plotifinbounds
  1680. %  **    \!initinboundscheck  --  set by \inboundscheck off/on to either
  1681. %  **       \relax  or  \!!initinboundscheck
  1682. %  \plotsymbolspacing  ** distance between consecutive plot positions
  1683. %  \!xS                ** starting x
  1684. %  \!yS                ** starting y
  1685. %  \!xE                ** ending   x
  1686. %  \!yE                ** ending   y
  1687. %  \!xdiff             ** x_end - x_start
  1688. %  \!ydiff             ** y_end - y_start
  1689. %  \!distacross        ** how far along curve next point to be plotted is
  1690. %  \!arclength         ** approximate length of arc for current interval
  1691. %  \!downlength        ** remaining length for "pen" to be down    
  1692. %  \!uplength          ** length for "pen" to be down    
  1693. %  \!intervalno        ** counts segments to curve
  1694. %  \totalarclength     ** cumulative distance along curve
  1695. %  \!npoints           ** approximately  (arc length / plotsymbolspacing)
  1696. %  **  Calls -- \!Pythag, \!divide, \!plot
  1697. %  **  \!start (XCOORD,YCOORD)
  1698. %  **  Sets initial point for linearly (or quadratically) interpolated curve
  1699. \def\!start (#1,#2){%
  1700.   \!plotxorigin=\!xorigin  \advance \!plotxorigin by \!plotsymbolxshift
  1701.   \!plotyorigin=\!yorigin  \advance \!plotyorigin by \!plotsymbolyshift
  1702.   \!xS=\!M{#1}\!xunit \!yS=\!M{#2}\!yunit
  1703.   \!rotateaboutpivot\!xS\!yS
  1704.   \!copylist\!UDlist\to\!!UDlist% **\!UDlist has the form \\{dimen1}\\{dimen2}..
  1705. %                                 ** Routine will draw dashed line with pen
  1706. %                                 ** down for dimen1, up for dimen2, ...
  1707.   \!getnextvalueof\!downlength\from\!!UDlist
  1708.   \!distacross=\!zpt%             ** 1st point goes at start of curve
  1709.   \!intervalno=0 %                ** initialize interval counter
  1710.   \global\totalarclength=\!zpt%   ** initialize distance traveled along curve
  1711.   \ignorespaces}
  1712. %  **  \!ljoin (XCOORD,YCOORD) 
  1713. %  **  Draws a straight line starting at the last point specified
  1714. %  **    by the most recent \!start, \!ljoin, or \!qjoin, and
  1715. %  **    ending at (XCOORD,YCOORD).
  1716. \def\!ljoin (#1,#2){%
  1717.   \advance\!intervalno by 1
  1718.   \!xE=\!M{#1}\!xunit \!yE=\!M{#2}\!yunit
  1719.   \!rotateaboutpivot\!xE\!yE
  1720.   \!xdiff=\!xE \advance \!xdiff by -\!xS%**  xdiff = xE - xS
  1721.   \!ydiff=\!yE \advance \!ydiff by -\!yS%**  ydiff = yE - yS
  1722.   \!Pythag\!xdiff\!ydiff\!arclength%     **  arclength = sqrt(xdiff**2+ydiff**2) 
  1723.   \global\advance \totalarclength by \!arclength%
  1724.   \!drawlinearsegment%   ** set by dashpat to \!linearsolid or \!lineardashed
  1725.   \!xS=\!xE \!yS=\!yE%   ** shift ending points to starting points
  1726.   \ignorespaces}
  1727. % **  The following routine is used to draw a "solid" line between (xS,yS)
  1728. % **  and (xE,yE).  Points are spaced nearly every  \plotsymbolspacing length
  1729. % **  along the line.  
  1730. \def\!linearsolid{%
  1731.   \!npoints=\!arclength
  1732.   \!countA=\plotsymbolspacing
  1733.   \divide\!npoints by \!countA%      ** now #pts =. arclength/plotsymbolspacing
  1734.   \ifnum \!npoints<1 
  1735.     \!npoints=1 
  1736.   \fi
  1737.   \divide\!xdiff by \!npoints
  1738.   \divide\!ydiff by \!npoints
  1739.   \!xpos=\!xS \!ypos=\!yS
  1740.   \loop\ifnum\!npoints>-1
  1741.     \!plotifinbounds
  1742.     \advance \!xpos by \!xdiff
  1743.     \advance \!ypos by \!ydiff
  1744.     \advance \!npoints by -1
  1745.   \repeat
  1746.   \ignorespaces}
  1747. % ** The following routine is used to draw a dashed line between (xS,yS)
  1748. % ** and (xE,yE). The dash pattern continues from the previous segment.
  1749. \def\!lineardashed{%
  1750.   \ifdim\!distacross>\!arclength
  1751.     \advance \!distacross by -\!arclength  %nothing to plot in this interval
  1752.   \else
  1753.     \loop\ifdim\!distacross<\!arclength
  1754. %     ** plot point, interpolating linearly in x and y
  1755.       \!divide\!distacross\!arclength\!dimenA%  ** dimA = across/arclength
  1756.       \!removept\!dimenA\!t%  ** \!t holds value in dimA, without the "pt"
  1757.       \!xpos=\!t\!xdiff \advance \!xpos by \!xS
  1758.       \!ypos=\!t\!ydiff \advance \!ypos by \!yS
  1759.       \!plotifinbounds
  1760.       \advance\!distacross by \plotsymbolspacing
  1761.       \!advancedashing
  1762.     \repeat  
  1763.     \advance \!distacross by -\!arclength%    ** prepare for next interval 
  1764.   \fi
  1765.   \ignorespaces}
  1766. \def\!!advancedashing{%
  1767.   \advance\!downlength by -\plotsymbolspacing
  1768.   \ifdim \!downlength>\!zpt
  1769.   \else
  1770.     \advance\!distacross by \!downlength
  1771.     \!getnextvalueof\!uplength\from\!!UDlist
  1772.     \advance\!distacross by \!uplength
  1773.     \!getnextvalueof\!downlength\from\!!UDlist
  1774.   \fi}
  1775. % ** \inboundscheckoff & \inboundscheckon: See Subsection 5.5 of the manual.
  1776. \def\inboundscheckoff{%
  1777.   \def\!plotifinbounds{\!plot(\!xpos,\!ypos)}%
  1778.   \def\!initinboundscheck{\relax}\ignorespaces}
  1779. \def\inboundscheckon{%
  1780.   \def\!plotifinbounds{\!!plotifinbounds}%
  1781.   \def\!initinboundscheck{\!!initinboundscheck}%
  1782.   \!initinboundscheck\ignorespaces} 
  1783. \inboundscheckoff
  1784. % ** The following code plots the current point only if it falls in the
  1785. % ** current plotarea.  It doesn't matter if the coordinate system has
  1786. % ** changed since the plotarea was set up.  However, shifts of the plot
  1787. % ** are ignored (how the plotsymbol stands relative to its plot position is
  1788. % ** unknown anyway).
  1789. \def\!!plotifinbounds{%
  1790.   \ifdim \!xpos<\!checkleft
  1791.   \else
  1792.     \ifdim \!xpos>\!checkright
  1793.     \else
  1794.       \ifdim \!ypos<\!checkbot
  1795.       \else
  1796.          \ifdim \!ypos>\!checktop
  1797.          \else
  1798.            \!plot(\!xpos,\!ypos)
  1799.          \fi 
  1800.       \fi
  1801.     \fi
  1802.   \fi}
  1803. \def\!!initinboundscheck{%
  1804.   \!checkleft=\!arealloc     \advance\!checkleft by \!xorigin
  1805.   \!checkright=\!arearloc    \advance\!checkright by \!xorigin
  1806.   \!checkbot=\!areabloc      \advance\!checkbot by \!yorigin
  1807.   \!checktop=\!areatloc      \advance\!checktop by \!yorigin}
  1808. % *********************************
  1809. % *** LOGTEN  (Log_10 function) ***
  1810. % *********************************
  1811. % ** \!logten{X}
  1812. % ** Calculates log_10 of X.  X and LOG10(X) are in fixed point notation.
  1813. % **  X must be positive; it may have an optional `+' sign; any number
  1814. % **  of digits may be specified for X.  The absolute error in LOG10(X) is
  1815. % **  less than .0001 (probably < .00006).  That's about as good as you
  1816. % **  hope for, since TEX only operates to 5 figures after the decimal
  1817. % **  point anyway.
  1818. %  \!rootten=3.162278pt       **** These are values are set in ALLOCATIONS
  1819. %  \!tenAe=2.543275pt  (=A5)
  1820. %  \!tenAc=2.773839pt  (=A3)
  1821. %  \!tenAa=8.690286pt  (=A1)
  1822. \def\!logten#1#2{%
  1823.   \expandafter\!!logten#1\!nil
  1824.   \!removept\!dimenF#2%
  1825.   \ignorespaces}
  1826. \def\!!logten#1#2\!nil{%
  1827.   \if -#1%
  1828.     \!dimenF=\!zpt
  1829.     \def\!next{\ignorespaces}%
  1830.   \else
  1831.     \if +#1%
  1832.       \def\!next{\!!logten#2\!nil}%
  1833.     \else
  1834.       \if .#1%
  1835.         \def\!next{\!!logten0.#2\!nil}%
  1836.       \else
  1837.         \def\!next{\!!!logten#1#2..\!nil}%
  1838.       \fi
  1839.     \fi
  1840.   \fi
  1841.   \!next}
  1842. \def\!!!logten#1#2.#3.#4\!nil{%
  1843.   \!dimenF=1pt %                 ** DimF holds log10 original argument
  1844.   \if 0#1%                      
  1845.     \!!logshift#3pt %            ** Argument < 1
  1846.   \else %                        ** Argument >= 1
  1847.     \!logshift#2/%               ** Shift decimal pt as many places
  1848.     \!dimenE=#1.#2#3pt %         **   as there are figures in #2
  1849.   \fi %                          ** Now dimE holds revised X want log10 of
  1850.   \ifdim \!dimenE<\!rootten%          ** Transform X to XX between sqrt(10) 
  1851.     \multiply \!dimenE 10 %           **   and 10*sqrt(10)
  1852.     \advance  \!dimenF -1pt
  1853.   \fi
  1854.   \!dimenG=\!dimenE%                  ** dimG <- (XX + 10)
  1855.     \advance\!dimenG 10pt
  1856.   \advance\!dimenE -10pt %            ** dimE <- (XX - 10)
  1857.   \multiply\!dimenE 10 %              ** dimE = 10*(XX-10)
  1858.   \!divide\!dimenE\!dimenG\!dimenE%   ** Now dimE=10t==10*(XX-10)/(XX+10)
  1859.   \!removept\!dimenE\!t%              ** !t=10t, with "pt" removed
  1860.   \!dimenG=\!t\!dimenE%               ** dimG=100t**2
  1861.   \!removept\!dimenG\!tt%             ** !tt=100t**2, with "pt" removed
  1862.   \!dimenH=\!tt\!tenAe%               ** dimH=10*a5*(10t)**2 /100
  1863.     \divide\!dimenH 100
  1864.   \advance\!dimenH \!tenAc%           ** ditto + 10*a3
  1865.   \!dimenH=\!tt\!dimenH%              ** ditto * (10t)**2 /100
  1866.     \divide\!dimenH 100   
  1867.   \advance\!dimenH \!tenAa%           ** ditto + 10*a1
  1868.   \!dimenH=\!t\!dimenH%               ** ditto * 10t / 100
  1869.     \divide\!dimenH 100 %             ** Now dimH = log10(XX) - 1
  1870.   \advance\!dimenF \!dimenH}%         ** dimF = log10(X)
  1871. \def\!logshift#1{%
  1872.   \if #1/%
  1873.     \def\!next{\ignorespaces}%
  1874.   \else
  1875.     \advance\!dimenF 1pt 
  1876.     \def\!next{\!logshift}%
  1877.   \fi 
  1878.   \!next}
  1879.  \def\!!logshift#1{%
  1880.    \advance\!dimenF -1pt
  1881.    \if 0#1%
  1882.      \def\!next{\!!logshift}%
  1883.    \else
  1884.      \if p#1%
  1885.        \!dimenF=1pt
  1886.        \def\!next{\!dimenE=1p}%
  1887.      \else
  1888.        \def\!next{\!dimenE=#1.}%
  1889.      \fi
  1890.    \fi
  1891.    \!next}
  1892. % ***********************************************************
  1893. % *** PICTURES (Basic setups for PiCtures; \put commands) ***
  1894. % ***********************************************************
  1895. % **  User Commands:
  1896. % **    \beginpicture
  1897. % **    \endpicture    
  1898. % **    \endpicturesave <XREG,YREG>
  1899. % **    \setcoordinatesystem units <XUNIT,YUNIT> point at XREF YREF
  1900. % **    \put {OBJECT} [ORIENTATION] <XSHIFT,YSHIFT> at XCOORD YCOORD
  1901. % **    \multiput {OJBECT} [ORIENTATION] <XSHIFT,YSHIFT>) at
  1902. % **      XCOORD YCOORD
  1903. % **      *NUMBER_OF_TIMES DXCOORD DYCOORD  /
  1904. % **    \accountingon
  1905. % **    \accountingoff
  1906. % **    \stack [ORIENTATION] <LEADING> {LIST OF ITEMS}
  1907. % **    \lines [ORIENTATION] {LINES}
  1908. % **    \Lines [ORIENTATION] {LINES}
  1909. % **    \setdimensionmode
  1910. % **    \setcoordinatemode
  1911. % **    \Xdistance
  1912. % **    \Ydistance
  1913. % **  Internal commands:
  1914. % **    \!setputobject{OBJECT}{[ORIENTATION]<XSHIFT,YSHIFT>}
  1915. % **    \!dimenput{OBJECT}[ORIENTATION]<XSHIFT,YSHIFT>(XDIMEN,YDIMEN)
  1916. % **    \!setdimenmode
  1917. % **    \!setcoordmode
  1918. % **    \!ifdimenmode
  1919. % **    \!ifcoordmode
  1920. % **  \beginpicture
  1921. % **  \endpicture
  1922. % **  \endpicturesave <XREG,YREG>
  1923. % **    \beginpicture ... \endpicture  creates an hbox.  Objects are
  1924. % **    placed in this box using the \put command and the like (see below).
  1925. % **    The location of an object is specified in terms of coordinate system(s)
  1926. % **    established by \setcoordinatesystem.  Each coordinate system (there
  1927. % **    might be just one) specifies the length of 1 horizontal unit, the length
  1928. % **    of 1 vertical unit, and the coordinates of a "reference point".  The
  1929. % **    reference points of various coordinate systems will be in the same
  1930. % **    physical location.  The macros keep track of the size of the objects
  1931. % **    and their locations. The resulting hbox is the smallest hbox which
  1932. % **    encloses all the objects, and whose TEK reference point is the point
  1933. % **    on the left edge of the box closest vertically to the PICTEX reference
  1934. % **    point. Using \endpicturesave, you can (globally) save the distance TEK's
  1935. % **    reference point is to the right (respectively, up from) PICTEX's 
  1936. % **    reference point in the dimension register \XREG (respectively \YREG). 
  1937. % **    You can then \put the picture OBJECT into a larger picture so that its
  1938. % **    reference point is at (XCOORD,YCOORD) with the command
  1939. % **      \put {picture OBJECT} [Bl] <\XREG, \YREG> at  XCOORD YCOORD 
  1940. % **  \beginpicture : See Subsection 1.1 of the manual.
  1941. \def\beginpicture{%
  1942.   \setbox\!picbox=\hbox\bgroup%
  1943.   \!xleft=\maxdimen  
  1944.   \!xright=-\maxdimen
  1945.   \!ybot=\maxdimen
  1946.   \!ytop=-\maxdimen}
  1947. % **  \endpicture : See Subsection 1.1 of the manual.
  1948. \def\endpicture{%
  1949.   \ifdim\!xleft=\maxdimen%  ** check if nothing was put in picbox
  1950.     \!xleft=\!zpt \!xright=\!zpt \!ybot=\!zpt \!ytop=\!zpt 
  1951.   \fi
  1952.   \global\!Xleft=\!xleft \global\!Xright=\!xright
  1953.   \global\!Ybot=\!ybot \global\!Ytop=\!ytop
  1954.   \egroup%
  1955.   \ht\!picbox=\!Ytop  \dp\!picbox=-\!Ybot
  1956.   \ifdim\!Ybot>\!zpt
  1957.   \else 
  1958.     \ifdim\!Ytop<\!zpt
  1959.       \!Ybot=\!Ytop
  1960.     \else
  1961.       \!Ybot=\!zpt
  1962.     \fi
  1963.   \fi
  1964.   \hbox{\kern-\!Xleft\lower\!Ybot\box\!picbox\kern\!Xright}}
  1965. % **  \endpicturesave : See Subsection 8.4 of the manual.
  1966. \def\endpicturesave <#1,#2>{%
  1967.   \endpicture \global #1=\!Xleft \global #2=\!Ybot \ignorespaces}
  1968. % **   \setcoordinatesystem units <XUNIT,YUNIT> 
  1969. % **     point at XREF YREF  
  1970. % **   Each of `units <XUNIT,YUNIT>' and `point at XREF YREF' 
  1971. % **     are optional.
  1972. % **   Unit lengths must be given in dimensions (e.g., <10pt,1in>).
  1973. % **     Default unit lengths are 1pt, 1pt, or previous unit lengths.
  1974. % **   Reference point is specified in current units (e.g., 3 5 ). 
  1975. % **     Default reference point is 0 0 , or previous reference point.
  1976. % **   Unit lengths and reference points obey TEX's scoping rules.
  1977. % **   See Subsection 1.2 of the manual.
  1978. \def\setcoordinatesystem{%
  1979.   \!ifnextchar{u}{\!getlengths }
  1980.     {\!getlengths units <\!xunit,\!yunit>}}
  1981. \def\!getlengths units <#1,#2>{%
  1982.   \!xunit=#1\relax
  1983.   \!yunit=#2\relax
  1984.   \!ifcoordmode 
  1985.     \let\!SCnext=\!SCccheckforRP
  1986.   \else
  1987.     \let\!SCnext=\!SCdcheckforRP
  1988.   \fi
  1989.   \!SCnext}
  1990. \def\!SCccheckforRP{%
  1991.   \!ifnextchar{p}{\!cgetreference }
  1992.     {\!cgetreference point at {\!xref} {\!yref} }}
  1993. \def\!cgetreference point at #1 #2 {%
  1994.   \edef\!xref{#1}\edef\!yref{#2}%
  1995.   \!xorigin=\!xref\!xunit  \!yorigin=\!yref\!yunit  
  1996.   \!initinboundscheck % ** See linear.tex
  1997.   \ignorespaces}
  1998. \def\!SCdcheckforRP{%
  1999.   \!ifnextchar{p}{\!dgetreference}%
  2000.     {\ignorespaces}}
  2001. \def\!dgetreference point at #1 #2 {%
  2002.   \!xorigin=#1\relax  \!yorigin=#2\relax
  2003.   \ignorespaces}
  2004. %  ** \put {OBJECT} [XY] <XDIMEN,YDIMEN> at (XCOORD,YCOORD)
  2005. %  **   `[XY]' and `<XDIMEN,YDIMEN>' are optional.
  2006. %  **   First OBJECT is placed in an hbox (the "objectbox") and then a
  2007. %  **     "reference point" is assigned to the objectbox as follows:
  2008. %  **     [1] first, the reference point is taken to be the center of the box;
  2009. %  **     [2] next, centering is overridden by the specifications
  2010. %  **           X=l -- reference point along the left edge of the objectbox
  2011. %  **           X=r -- reference point along the right edge of the objectbox
  2012. %  **           Y=b -- reference point along the bottom edge of the objectbox
  2013. %  **           Y=B -- reference point along the Baseline of the objectbox
  2014. %  **           Y=t -- reference point along the top edge of the objectbox;
  2015. %  **     [3] finally the reference point is shifted left by XDIMEN, down
  2016. %  **           by YDIMEN  (both default to 0pt).
  2017. %  **   The objectbox is placed within PICBOX with its reference point at  
  2018. %  **     (XCOORD,YCOORD). 
  2019. %  **   If OBJECT is a saved box, say  box0, you have to write
  2020. %  **     \put{\box0}...   or  \put{\copy0}...
  2021. %  **   The objectbox is void after the put.
  2022. %  **   See Subsection 2.1 of the manual.
  2023. \long\def\put#1#2 at #3 #4 {%
  2024.   \!setputobject{#1}{#2}%
  2025.   \!xpos=\!M{#3}\!xunit  \!ypos=\!M{#4}\!yunit  
  2026.   \!rotateaboutpivot\!xpos\!ypos%
  2027.   \advance\!xpos -\!xorigin  \advance\!xpos -\!xshift
  2028.   \advance\!ypos -\!yorigin  \advance\!ypos -\!yshift
  2029.   \kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos%
  2030.   \!doaccounting\ignorespaces}
  2031. %  **   \multiput etc.  Like  \put.  The objectbox is not voided until the
  2032. %  **     termininating /, and is placed repeatedly with:
  2033. %  **     XCOORD YCOORD -- the objectbox is put down with its reference point
  2034. %  **       at (XCOORD,YCOORD);
  2035. %  **     *N DXCOORD DYCOORD -- each of N times the current
  2036. %  **       (xcoord,ycoord) is incremented by (DXCOORD,DYCOORD), and the
  2037. %  **       objectbox is put down with its reference point at (xcoord,ycoord)
  2038. %  **       (This specification has to follow an XCOORD YCOORD pair)
  2039. %  **     See Subsection 2.2 of the manual.
  2040. \long\def\multiput #1#2 at {%
  2041.   \!setputobject{#1}{#2}%
  2042.   \!ifnextchar"{\!putfromfile}{\!multiput}}
  2043. \def\!putfromfile"#1"{%
  2044.   \expandafter\!multiput \input #1 /}
  2045. \def\!multiput{%
  2046.   \futurelet\!nextchar\!!multiput}
  2047. \def\!!multiput{%
  2048.   \if *\!nextchar
  2049.     \def\!nextput{\!alsoby}%
  2050.   \else
  2051.     \if /\!nextchar
  2052.       \def\!nextput{\!finishmultiput}%
  2053.     \else
  2054.       \def\!nextput{\!alsoat}%
  2055.     \fi
  2056.   \fi
  2057.   \!nextput}
  2058. \def\!finishmultiput/{%
  2059.   \setbox\!putobject=\hbox{}%
  2060.   \ignorespaces}
  2061. %  **   \!alsoat XCOORD YCOORD 
  2062. %  **     The objectbox is put down with reference point at XCOORD,YCOORD
  2063. \def\!alsoat#1 #2 {%
  2064.   \!xpos=\!M{#1}\!xunit  \!ypos=\!M{#2}\!yunit  
  2065.   \!rotateaboutpivot\!xpos\!ypos%
  2066.   \advance\!xpos -\!xorigin  \advance\!xpos -\!xshift
  2067.   \advance\!ypos -\!yorigin  \advance\!ypos -\!yshift
  2068.   \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos%
  2069.   \!doaccounting
  2070.   \!multiput}
  2071. % **   \!alsoby*N DXCOORD DYCOORD
  2072. % **     N times, the current (XCOORD,YCOORD) is advanced by (DXCOORD,DYCOORD),
  2073. % **     and the current (shifted, oriented) OBJECT is put down.
  2074. \def\!alsoby*#1 #2 #3 {%
  2075.   \!dxpos=\!M{#2}\!xunit \!dypos=\!M{#3}\!yunit 
  2076.   \!rotateonly\!dxpos\!dypos
  2077.   \!ntemp=#1%
  2078.   \!!loop\ifnum\!ntemp>0
  2079.     \advance\!xpos by \!dxpos  \advance\!ypos by \!dypos
  2080.     \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos%
  2081.     \advance\!ntemp by -1
  2082.   \repeat
  2083.   \!doaccounting 
  2084.   \!multiput}
  2085. % **  \accountingoff : Suspends PiCTeX's accounting of the aggregate
  2086. % **    size of the picture box.
  2087. % **  \accounting on : Reinstates accounting.
  2088. % **  See Subsection 8.2 of the manual.
  2089. \def\accountingon{\def\!doaccounting{\!!doaccounting}\ignorespaces}
  2090. \def\accountingoff{\def\!doaccounting{}\ignorespaces}
  2091. \accountingon
  2092. \def\!!doaccounting{%
  2093.   \!xtemp=\!xpos  
  2094.   \!ytemp=\!ypos
  2095.   \ifdim\!xtemp<\!xleft 
  2096.      \!xleft=\!xtemp 
  2097.   \fi
  2098.   \advance\!xtemp by  \!wd 
  2099.   \ifdim\!xright<\!xtemp 
  2100.     \!xright=\!xtemp
  2101.   \fi
  2102.   \advance\!ytemp by -\!dp
  2103.   \ifdim\!ytemp<\!ybot  
  2104.     \!ybot=\!ytemp
  2105.   \fi
  2106.   \advance\!ytemp by  \!dp
  2107.   \advance\!ytemp by  \!ht 
  2108.   \ifdim\!ytemp>\!ytop  
  2109.     \!ytop=\!ytemp  
  2110.   \fi}
  2111. \long\def\!setputobject#1#2{%
  2112.   \setbox\!putobject=\hbox{#1}%
  2113.   \!ht=\ht\!putobject  \!dp=\dp\!putobject  \!wd=\wd\!putobject
  2114.   \wd\!putobject=\!zpt
  2115.   \!xshift=.5\!wd   \!yshift=.5\!ht   \advance\!yshift by -.5\!dp
  2116.   \edef\!putorientation{#2}%
  2117.   \expandafter\!SPOreadA\!putorientation[]\!nil%
  2118.   \expandafter\!SPOreadB\!putorientation<\!zpt,\!zpt>\!nil\ignorespaces}
  2119. \def\!SPOreadA#1[#2]#3\!nil{\!etfor\!orientation:=#2\do\!SPOreviseshift}
  2120. \def\!SPOreadB#1<#2,#3>#4\!nil{\advance\!xshift by -#2\advance\!yshift by -#3}
  2121. \def\!SPOreviseshift{%
  2122.   \if l\!orientation 
  2123.     \!xshift=\!zpt
  2124.   \else 
  2125.     \if r\!orientation 
  2126.       \!xshift=\!wd
  2127.     \else 
  2128.       \if b\!orientation
  2129.         \!yshift=-\!dp
  2130.       \else 
  2131.         \if B\!orientation 
  2132.           \!yshift=\!zpt
  2133.         \else 
  2134.           \if t\!orientation 
  2135.             \!yshift=\!ht
  2136.           \fi 
  2137.         \fi
  2138.       \fi
  2139.     \fi
  2140.   \fi}
  2141. %  **  \!dimenput{OBJECT} <XDIMEN,YDIMEN> [XY] (XLOC,YLOC)
  2142. %  **    This is an internal put routine, similar to \put, except that
  2143. %  **    XLOC=distance right from reference point, YLOC=distance up from
  2144. %  **    reference point. XLOC and YLOC are dimensions, so this routine
  2145. %  **    is completely independent of the current coordinate system. 
  2146. %  **    This routine does NOT do ROTATIONS.
  2147. \long\def\!dimenput#1#2(#3,#4){%
  2148.   \!setputobject{#1}{#2}%
  2149.   \!xpos=#3\advance\!xpos by -\!xshift
  2150.   \!ypos=#4\advance\!ypos by -\!yshift
  2151.   \kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos%
  2152.   \!doaccounting\ignorespaces}
  2153. %  ** The following macros permit the picture drawing routines to be used 
  2154. %  ** either in the default "coordinate mode", or in "dimension mode".
  2155. %  **   In coordinate mode  \!M(1.5,\!xunit)    expands to  1.5\!xunit
  2156. %  **   In dimension  mode  \!M(1.5pt,\!xunit)  expands to  1.5pt
  2157. %  ** Dimension mode is useful in coding macros.
  2158. %  ** Any special purpose picture macro that sets dimension mode should 
  2159. %  ** reset coordinate mode before completion.
  2160. %  ** See Subsection 9.2 of the manual.
  2161. \def\!setdimenmode{%
  2162.   \let\!M=\!M!!\ignorespaces}
  2163. \def\!setcoordmode{%
  2164.   \let\!M=\!M!\ignorespaces}
  2165. \def\!ifcoordmode{%
  2166.   \ifx \!M \!M!}
  2167. \def\!ifdimenmode{%
  2168.   \ifx \!M \!M!!}
  2169. \def\!M!#1#2{#1#2} 
  2170. \def\!M!!#1#2{#1}
  2171. \!setcoordmode
  2172. \let\setdimensionmode=\!setdimenmode
  2173. \let\setcoordinatemode=\!setcoordmode
  2174. %  ** \Xdistance{XCOORD}, \Ydistance{YCOORD}  are the horizontal and
  2175. %  **   vertical distances from the origin (0,0) to the point
  2176. %  **   (XCOORD,YCOORD)  in the current coordinate system.
  2177. %  ** See Subsection 9.2 of the manual.
  2178. \def\Xdistance#1{%
  2179.   \!M{#1}\!xunit
  2180.   \ignorespaces}
  2181. \def\Ydistance#1{%
  2182.   \!M{#1}\!yunit
  2183.   \ignorespaces}
  2184. % ** The following macros -- \stack, \line, and \Lines -- are useful for
  2185. % **   annotating PiCtures. They can be used outside the \beginpicture ...
  2186. % **   \endpicture environment.
  2187. % ** \stack [POSITIONING] <LEADING> {VALUESLIST}
  2188. % ** Builds a vertical stack of the values in VALUESLIST. Values in
  2189. % ** VALUESLIST are separated by commas.  In the resulting stack, values are
  2190. % ** centered by default, and positioned flush left (right) if 
  2191. % ** POSITIONING = l (r).  Values are separated vertically by LEADING,
  2192. % ** which defaults to \stackleading.
  2193. % ** See Subsection 2.3 of the manual.
  2194. \def\stack{%
  2195.   \!ifnextchar[{\!stack}{\!stack[c]}}
  2196. \def\!stack[#1]{%
  2197.   \let\!lglue=\hfill \let\!rglue=\hfill
  2198.   \expandafter\let\csname !#1glue\endcsname=\relax
  2199.   \!ifnextchar<{\!!stack}{\!!stack<\stackleading>}}
  2200. \def\!!stack<#1>#2{%
  2201.   \vbox{\def\!valueslist{}\!ecfor\!value:=#2\do{%
  2202.     \expandafter\!rightappend\!value\withCS{\\}\to\!valueslist}%
  2203.     \!lop\!valueslist\to\!value
  2204.     \let\\=\cr\lineskiplimit=\maxdimen\lineskip=#1%
  2205.     \baselineskip=-1000pt\halign{\!lglue##\!rglue\cr \!value\!valueslist\cr}}%
  2206.   \ignorespaces}
  2207. % ** \lines [POSITIONING] {LINES}
  2208. % ** Builds a vertical array of the lines in LINES. Each line in LINES
  2209. % ** is terminated by a \cr.  In the resulting array, lines are
  2210. % ** centered by default, and positioned flush left (right) if 
  2211. % ** POSITIONING = l (r).  The lines in the array are subject to TeX's
  2212. % ** usual spacing rules: in particular the baselines are ordinarily an equal
  2213. % ** distance apart. The baseline of the array is the baseline of the
  2214. % ** the bottom line.
  2215. % ** See Subsection 2.3 of the manual.
  2216. \def\lines{%
  2217.   \!ifnextchar[{\!lines}{\!lines[c]}}
  2218. \def\!lines[#1]#2{%
  2219.   \let\!lglue=\hfill \let\!rglue=\hfill
  2220.   \expandafter\let\csname !#1glue\endcsname=\relax
  2221.   \vbox{\halign{\!lglue##\!rglue\cr #2\crcr}}%
  2222.   \ignorespaces}
  2223. % ** \Lines [POSITIONING] {LINES}
  2224. % ** Like \lines, but the baseline of the array is the baseline of the
  2225. % ** top line.  See Subsection 2.3 of the manual.
  2226. \def\Lines{%
  2227.   \!ifnextchar[{\!Lines}{\!Lines[c]}}
  2228. \def\!Lines[#1]#2{%
  2229.   \let\!lglue=\hfill \let\!rglue=\hfill
  2230.   \expandafter\let\csname !#1glue\endcsname=\relax
  2231.   \vtop{\halign{\!lglue##\!rglue\cr #2\crcr}}%
  2232.   \ignorespaces}
  2233. % *********************************************
  2234. % *** PLOTTING (Things to do with plotting) ***
  2235. % *********************************************
  2236. % **  User commands
  2237. % **    \setplotsymbol ({PLOTSYMBOL} [ORIENTATION] <XSHIFT,YSHIFT>)
  2238. % **    \savelinesandcurves on "FILE_NAME"
  2239. % **    \dontsavelinesandcurves
  2240. % **    \writesavefile {MESSAGE}
  2241. % **    \replot {FILE_NAME}
  2242. % **  Internal command
  2243. % **    \!plot(XDIMEN,YDIMEN)
  2244. % **  \setplotsymbol ({PLOTSYMBOL} [ ] < , >)
  2245. % **  Save PLOTSYMBOL away in an hbox for use with curve plotting routines
  2246. % **  See Subsection 5.2 of the manual.
  2247. \def\setplotsymbol(#1#2){%
  2248.   \!setputobject{#1}{#2}
  2249.   \setbox\!plotsymbol=\box\!putobject%
  2250.   \!plotsymbolxshift=\!xshift 
  2251.   \!plotsymbolyshift=\!yshift 
  2252.   \ignorespaces}
  2253. \font\fiverm=cmr5
  2254. \setplotsymbol({\fiverm .})%       ** initialize plotsymbol
  2255. % **  \!plot is either \!!plot (when no lines and curves are being saved) or
  2256. % **                   \!!!plot (when   lines and curves are being saved)
  2257. % **  \!!plot(XDIMEN,YDIMEN)
  2258. % **  Places the current plotsymbol a horizontal distance=XDIMEN-xorigin 
  2259. % **    and a vertical distance=YDIMEN-yorigin from the current
  2260. % **    reference point.  
  2261. \def\!!plot(#1,#2){%
  2262.   \!dimenA=-\!plotxorigin \advance \!dimenA by #1%    ** over
  2263.   \!dimenB=-\!plotyorigin \advance \!dimenB by #2%    ** up
  2264.   \kern\!dimenA\raise\!dimenB\copy\!plotsymbol\kern-\!dimenA%
  2265.   \ignorespaces}
  2266. % **  \!!!plot(XDIMEN,YDIMEN)
  2267. % **  Like \!!plot, but also saves the plot location in units of 
  2268. % **    scaled point, on file `replotfile'
  2269. \def\!!!plot(#1,#2){%
  2270.   \!dimenA=-\!plotxorigin \advance \!dimenA by #1%    ** over
  2271.   \!dimenB=-\!plotyorigin \advance \!dimenB by #2%    ** up
  2272.   \kern\!dimenA\raise\!dimenB\copy\!plotsymbol\kern-\!dimenA%
  2273.   \!countE=\!dimenA
  2274.   \!countF=\!dimenB
  2275.   \immediate\write\!replotfile{\the\!countE,\the\!countF.}%
  2276.   \ignorespaces}
  2277. % ** \savelinesandcurves on "FILE_NAME"
  2278. % **   Switch to save locations used for plotting lines and curves
  2279. % **   (No advantage in saving locations for solid lines; however
  2280. % **   replotting curve locations speeds things up by a factor of about 4. 
  2281. % ** \dontsavelinesandcurves
  2282. % **   Terminates \savelinesandcurves. The default.
  2283. % ** See Subsection 5.6 of the manual.
  2284. \def\savelinesandcurves on "#1" {%
  2285.   \immediate\closeout\!replotfile
  2286.   \immediate\openout\!replotfile=#1%
  2287.   \let\!plot=\!!!plot}
  2288. \def\dontsavelinesandcurves {%
  2289.   \let\!plot=\!!plot}
  2290. \dontsavelinesandcurves
  2291. % ** \writesavefile {MESSAGE}
  2292. % ** The message is preceded by a "%", so that it won't interfere
  2293. % ** with replotting.
  2294. % ** See Subsection 5.6 of the manual.
  2295. {\catcode`\%=11\xdef\!Commentsignal{%}}
  2296. \def\writesavefile#1 {%
  2297.   \immediate\write\!replotfile{\!Commentsignal #1}%
  2298.   \ignorespaces}
  2299. % ** \replot "FILE_NAME"
  2300. % **   Replots the locations saved earlier under \savelinesandcurves
  2301. % **   on "FILE_NAME"
  2302. % ** See Subsection 5.6 of the manual.
  2303. \def\replot"#1" {%
  2304.   \expandafter\!replot\input #1 /}
  2305. \def\!replot#1,#2. {%
  2306.   \!dimenA=#1sp
  2307.   \kern\!dimenA\raise#2sp\copy\!plotsymbol\kern-\!dimenA
  2308.   \futurelet\!nextchar\!!replot}
  2309. \def\!!replot{%
  2310.   \if /\!nextchar 
  2311.     \def\!next{\!finish}%
  2312.   \else
  2313.     \def\!next{\!replot}%
  2314.   \fi
  2315.   \!next}
  2316. % **************************************************
  2317. % ***  PYTHAGORAS  (Euclidean distance function) ***
  2318. % **************************************************
  2319. % ** User command:
  2320. % **   \placehypotenuse for <dimension1> and <dimension2> in <register> 
  2321. % ** Internal command:
  2322. % **   \!Pythag{X}{Y}{Z}
  2323. % **     Input X,Y are dimensions, or dimension registers.
  2324. % **     Output Z == sqrt(X**2+Y**2) must be a dimension register.
  2325. % **     Assumes that |X|+|Y| < 2048pt (about 28in).
  2326. % ** Without loss of generality, suppose  x>0, y>0.  Put s = x+y,
  2327. % **   z = sqrt(x**2+y**2). Then  z = s*f,  where  f = sqrt(t**2 + (1-t)**2)
  2328. % **   = sqrt((1+tau**2)/2), where  t = x/s  and  tau = 2(t-1/2) .
  2329. % ** Uses the \!divide macro (which uses registers \!dimenA--\!dimenD.
  2330. % ** Uses the \!removept macro   (e.g., 123.45pt --> 123.45)
  2331. % ** Uses registers \!dimenE--\!dimenI.
  2332. \def\!Pythag#1#2#3{%
  2333.   \!dimenE=#1\relax                                     
  2334.   \ifdim\!dimenE<\!zpt 
  2335.     \!dimenE=-\!dimenE 
  2336.   \fi%                                            ** dimE = |x|
  2337.   \!dimenF=#2\relax
  2338.   \ifdim\!dimenF<\!zpt 
  2339.     \!dimenF=-\!dimenF 
  2340.   \fi%                                            ** dimF = |y|
  2341.   \advance \!dimenF by \!dimenE%                  ** dimF = s = |x|+|y|
  2342.   \ifdim\!dimenF=\!zpt 
  2343.     \!dimenG=\!zpt%                               ** dimG = z = sqrt(x**2+y**2)
  2344.   \else 
  2345.     \!divide{8\!dimenE}\!dimenF\!dimenE%          ** now dimE = 8t = (8|x|)/s
  2346.     \advance\!dimenE by -4pt%                     ** 8tau = (8t-4)*2
  2347.       \!dimenE=2\!dimenE%                         **   (tau = 2*t - 1)
  2348.     \!removept\!dimenE\!!t%                       ** 8tau, without "pt"
  2349.     \!dimenE=\!!t\!dimenE%                        ** (8tau)**2, in pts
  2350.     \advance\!dimenE by 64pt%                     ** u = [64 + (8tau)**2]/2
  2351.     \divide \!dimenE by 2%                        **   [u = (8f)**2]
  2352.     \!dimenH=7pt%                                 ** initial guess g at sqrt(u)
  2353.     \!!Pythag\!!Pythag\!!Pythag%                  ** 3 iterations give sqrt(u)
  2354.     \!removept\!dimenH\!!t%                       ** 8f=sqrt(u), without "pt"
  2355.     \!dimenG=\!!t\!dimenF%                        ** z = (8f)*s/8
  2356.     \divide\!dimenG by 8
  2357.   \fi
  2358.   #3=\!dimenG
  2359.   \ignorespaces}
  2360. \def\!!Pythag{%                                   ** Newton-Raphson for sqrt
  2361.   \!divide\!dimenE\!dimenH\!dimenI%               ** v = u/g
  2362.   \advance\!dimenH by \!dimenI%                   ** g <-- (g + u/g)/2
  2363.     \divide\!dimenH by 2}
  2364. % **  \placehypotenuse for <XI> and <ETA> in <ZETA>
  2365. % **  See Subsection 9.3 of the manual.
  2366. \def\placehypotenuse for <#1> and <#2> in <#3> {%
  2367.   \!Pythag{#1}{#2}{#3}}
  2368. % **********************************************
  2369. % *** QUADRATIC ARC  (Draws a quadratic arc) ***
  2370. % **********************************************
  2371. % **  Internal command
  2372. % **    \!qjoin (XCOORD1,YCOORD1) (XCOORD2,YCOORD2)
  2373. % **  \!qjoin (XCOORD1,YCOORD1) (XCOORD2,YCOORD2)
  2374. % **  Draws an arc starting at the (last) point specified by the most recent
  2375. % **  \!qjoin, or \!ljoin, or \!start  and passing through (X_1,Y_1), (X_2,Y_2).
  2376. % **  Uses quadratic interpolation in both  x  and  y:  
  2377. % **    x(t), 0 <= t <= 1, interpolates  x_0, x_1, x_2  at  t=0, .5, 1
  2378. % **    y(t), 0 <= t <= 1, interpolates  y_0, y_1, y_2  at  t=0, .5, 1
  2379. \def\!qjoin (#1,#2) (#3,#4){%
  2380.   \advance\!intervalno by 1
  2381.   \!ifcoordmode
  2382.     \edef\!xmidpt{#1}\edef\!ymidpt{#2}%
  2383.   \else
  2384.     \!dimenA=#1\relax \edef\!xmidpt{\the\!dimenA}%
  2385.     \!dimenA=#2\relax \edef\!ymidpt{\the\!dimenA}%
  2386.   \fi
  2387.   \!xM=\!M{#1}\!xunit  \!yM=\!M{#2}\!yunit   \!rotateaboutpivot\!xM\!yM
  2388.   \!xE=\!M{#3}\!xunit  \!yE=\!M{#4}\!yunit   \!rotateaboutpivot\!xE\!yE
  2389. % ** Find coefficients for x(t)=a_x + b_x*t + c_x*t**2
  2390.   \!dimenA=\!xM  \advance \!dimenA by -\!xS%   ** dimA = I = xM - xS
  2391.   \!dimenB=\!xE  \advance \!dimenB by -\!xM%   ** dimB = II = xE-xM
  2392.   \!xB=3\!dimenA \advance \!xB by -\!dimenB%   ** b=3I-II
  2393.   \!xC=2\!dimenB \advance \!xC by -2\!dimenA%  ** c=2(II-I)
  2394. % ** Find coefficients for y(t)=y_x + b_y*t + c_y*t**2
  2395.   \!dimenA=\!yM  \advance \!dimenA by -\!yS%   
  2396.   \!dimenB=\!yE  \advance \!dimenB by -\!yM%  
  2397.   \!yB=3\!dimenA \advance \!yB by -\!dimenB%  
  2398.   \!yC=2\!dimenB \advance \!yC by -2\!dimenA% 
  2399. % ** Use Simpson's rule to calculate arc length over [0,1/2]:
  2400. % **   arc length = 1/2[1/6 f(0) + 4/6 f(1/4) + 1/6 f(1/2)]
  2401. % ** with f(t) = sqrt(x'(t)**2 + y'(t)**2).
  2402.   \!xprime=\!xB  \!yprime=\!yB%          ** x'(t) = b + 2ct
  2403.   \!dxprime=.5\!xC  \!dyprime=.5\!yC%    ** dt=1/4 ==> dx'(t) = c/2
  2404.   \!getf \!midarclength=\!dimenA
  2405.   \!getf \advance \!midarclength by 4\!dimenA
  2406.   \!getf \advance \!midarclength by \!dimenA
  2407.   \divide \!midarclength by 12
  2408. % ** Get arc length over [0,1].
  2409.   \!arclength=\!dimenA
  2410.   \!getf \advance \!arclength by 4\!dimenA
  2411.   \!getf \advance \!arclength by \!dimenA
  2412.   \divide \!arclength by 12%             ** Now have arc length over [1/2,1]
  2413.   \advance \!arclength by \!midarclength
  2414.   \global\advance \totalarclength by \!arclength
  2415. % ** Check to see if there's anything to plot in this interval
  2416.   \ifdim\!distacross>\!arclength 
  2417.     \advance \!distacross by -\!arclength%   ** nothing 
  2418.   \else
  2419.     \!initinverseinterp%  ** initialize for inverse interpolation on arc length
  2420.     \loop\ifdim\!distacross<\!arclength%     ** loop over points on arc 
  2421.       \!inverseinterp%    ** find  t  such that arc length[0,t] = distacross,
  2422. %                         **   using inverse quadratic interpolation
  2423. %                         ** now evaluate x(t)=(c*t + b)*t + a
  2424.       \!xpos=\!t\!xC \advance\!xpos by \!xB
  2425.         \!xpos=\!t\!xpos \advance \!xpos by \!xS
  2426. %                                             ** evaluate y(t)
  2427.       \!ypos=\!t\!yC \advance\!ypos by \!yB
  2428.         \!ypos=\!t\!ypos \advance \!ypos by \!yS
  2429.       \!plotifinbounds%                       ** plot point if in bounds
  2430.       \advance\!distacross \plotsymbolspacing%** advance arc length for next pt
  2431.       \!advancedashing%                       ** see "linear"
  2432.     \repeat  
  2433.     \advance \!distacross by -\!arclength%    ** prepare for next interval 
  2434.   \fi
  2435.   \!xS=\!xE%              ** shift ending points to starting points
  2436.   \!yS=\!yE
  2437.   \ignorespaces}
  2438. % ** \!getf -- Calculates sqrt(x'(t)**2 + y'(t)**2) and advances
  2439. % **   x'(t) and y'(t)
  2440. \def\!getf{\!Pythag\!xprime\!yprime\!dimenA%
  2441.   \advance\!xprime by \!dxprime
  2442.   \advance\!yprime by \!dyprime}
  2443. % ** \!initinverseinterp -- initializes for inverse quadratic interpolation
  2444. % ** of arc length provided  1/3 < midarclength/arclength < 2/3; otherwise
  2445. % ** initializes for inverse linear interpolation.
  2446. \def\!initinverseinterp{%
  2447.   \ifdim\!arclength>\!zpt
  2448.     \!divide{8\!midarclength}\!arclength\!dimenE% ** dimE=8w=8r/s, where  r 
  2449. %                                               **  = midarclength, s=arclength
  2450. % **  Test for  w  out of range:  w<1/3  or w>2/3
  2451.     \ifdim\!dimenE<\!wmin \!setinverselinear
  2452.     \else 
  2453.       \ifdim\!dimenE>\!wmax \!setinverselinear
  2454.       \else%                                    ** w  in range: initialize
  2455.         \def\!inverseinterp{\!inversequad}\ignorespaces
  2456. % **     Calculate the coefficients  \!beta  and  \!gamma  of the quadratic
  2457. % **                    t = \!beta*v + \!gamma*v**2
  2458. % **     taking the values  t=0, 1/2, 1  at  v=0, w==r/s, 1  respectively:
  2459. % **        \!beta = (1/2 - w**2)/[w(1-w)] 
  2460. % **        \!gamma = 1 - beta.
  2461.          \!removept\!dimenE\!Ew%           **  8w, without "pt"
  2462.          \!dimenF=-\!Ew\!dimenE%           **  -(8w)**2
  2463.          \advance\!dimenF by 32pt%         **  32 - (8w)**2
  2464.          \!dimenG=8pt 
  2465.          \advance\!dimenG by -\!dimenE%    **  8 - 8w
  2466.          \!dimenG=\!Ew\!dimenG%            **  (8w)*(8-8w)
  2467.          \!divide\!dimenF\!dimenG\!beta%   **  beta = (32-(8w)**2)/(8w(8-8w))
  2468. %                                          **       = (1/2 - w**2)/(w(1-w))
  2469.          \!gamma=1pt
  2470.          \advance \!gamma by -\!beta%      **  gamma = 1-beta
  2471.       \fi%       ** end of the \ifdim\!dimenE>\!wmax
  2472.     \fi%         ** end of the \ifdim\!dimenE<\!wmin
  2473.   \fi%           ** end of the \ifdim\!arclength>\!zpt
  2474.   \ignorespaces}
  2475. % ** For 0 <= t <= 1, let AL(t) = arclength[0,t]/arclength[0,1]; note
  2476. % ** AL(0)=0, AL(1/2)=midarclength/arclength, AL(1)=1.  This routine
  2477. % ** calculates an approximation to AL^{-1}(distance across/arclength),
  2478. % ** using the assumption that AL^{-1} is quadratic.  Specifically, 
  2479. % ** it finds  t  such that
  2480. % **    AL^{-1}(v) =. t = v*(\!beta + \!gamma*v)
  2481. % ** where  \!beta  and  \!gamma  are set by \!initinv, and where
  2482. % ** v=distance across/arclength
  2483. \def\!inversequad{%
  2484.   \!divide\!distacross\!arclength\!dimenG%   ** dimG = v = distacross/arclength
  2485.   \!removept\!dimenG\!v%                     ** v, without "pt"
  2486.   \!dimenG=\!v\!gamma%                       ** gamma*v
  2487.   \advance\!dimenG by \!beta%                ** beta + gamma*v
  2488.   \!dimenG=\!v\!dimenG%                      ** t = v*(beta + gamma*v)
  2489.   \!removept\!dimenG\!t}%                    ** t, without "pt"
  2490. % ** When  w <= 1/3  or  w >= 2/3, the following routine writes (using
  2491. % ** plain TEK's \wlog command) a warning message on the user's log file,
  2492. % ** and initializes for inverse linear interpolation on arc length.
  2493. \def\!setinverselinear{%
  2494.   \def\!inverseinterp{\!inverselinear}%
  2495.   \divide\!dimenE by 8 \!removept\!dimenE\!t
  2496.   \!countC=\!intervalno \multiply \!countC 2
  2497.   \!countB=\!countC     \advance \!countB -1
  2498.   \!countA=\!countB     \advance \!countA -1
  2499.   \wlog{\the\!countB th point (\!xmidpt,\!ymidpt) being plotted 
  2500.     doesn't lie in the}%
  2501.   \wlog{ middle third of the arc between the \the\!countA th 
  2502.     and \the\!countC th points:}%
  2503.   \wlog{ [arc length \the\!countA\space to \the\!countB]/[arc length 
  2504.     \the \!countA\space to \the\!countC]=\!t.}%
  2505.   \ignorespaces}
  2506. % **  Inverse linear interpolation
  2507. \def\!inverselinear{% 
  2508.   \!divide\!distacross\!arclength\!dimenG
  2509.   \!removept\!dimenG\!t}
  2510. % **************************************
  2511. % **  ROTATIONS  (Handles rotations) ***
  2512. % **************************************
  2513. % ** User commands
  2514. % **   \startrotation [by COS_OF_ANGLE SIN_OF_ANGLE] [about XPIVOT YPIVOT]
  2515. % **   \stoprotation
  2516. % **   \startrotation [by COS_OF_ANGLE SIN_OF_ANGLE] [about XPIVOT YPIVOT]
  2517. % ** Future (XCOORD,YCOORD)'s will be rotated about (XPIVOT,YPIVOT) 
  2518. % ** by the angle with the give COS and SIN. Both fields are optional.
  2519. % ** [COS,SIN] defaults to previous value, or (1,0).
  2520. % ** (XPIVOT,YPIVOT) defaults to previous value, or (0,0)
  2521. % ** You can't change the coordinate system in the scope of a rotation.
  2522. % ** See Subsection 9.1 of the manual.
  2523. \def\startrotation{%
  2524.   \let\!rotateaboutpivot=\!!rotateaboutpivot
  2525.   \let\!rotateonly=\!!rotateonly
  2526.   \!ifnextchar{b}{\!getsincos }%
  2527.     {\!getsincos by {\!cosrotationangle} {\!sinrotationangle} }}
  2528. \def\!getsincos by #1 #2 {%
  2529.   \edef\!cosrotationangle{#1}%
  2530.   \edef\!sinrotationangle{#2}%
  2531.   \!ifcoordmode 
  2532.     \let\!ROnext=\!ccheckforpivot
  2533.   \else
  2534.     \let\!ROnext=\!dcheckforpivot
  2535.   \fi
  2536.   \!ROnext}
  2537. \def\!ccheckforpivot{%
  2538.   \!ifnextchar{a}{\!cgetpivot}%
  2539.     {\!cgetpivot about {\!xpivotcoord} {\!ypivotcoord} }}
  2540. \def\!cgetpivot about #1 #2 {%
  2541.   \edef\!xpivotcoord{#1}%
  2542.   \edef\!ypivotcoord{#2}%
  2543.   \!xpivot=#1\!xunit  \!ypivot=#2\!yunit
  2544.   \ignorespaces}
  2545. \def\!dcheckforpivot{%
  2546.   \!ifnextchar{a}{\!dgetpivot}{\ignorespaces}}
  2547. \def\!dgetpivot about #1 #2 {%
  2548.   \!xpivot=#1\relax  \!ypivot=#2\relax
  2549.   \ignorespaces}
  2550. % ** Following terminates rotation.
  2551. % ** See Subsection 9.1 of the manual.
  2552. \def\stoprotation{%
  2553.   \let\!rotateaboutpivot=\!!!rotateaboutpivot
  2554.   \let\!rotateonly=\!!!rotateonly
  2555.   \ignorespaces}
  2556. % ** !!rotateaboutpivot{XREG}{YREG}
  2557. % ** XREG <-- xpvt + cos(angle)*(XREG-xpvt) - sin(angle)*(YREG-ypvt)
  2558. % ** YREG <-- ypvt + cos(angle)*(YREG-ypvt) + sin(angle)*(XREG-xpvt)
  2559. % ** XREG,YREG are dimension registers. Can't be \!dimenA to \!dimenD
  2560. \def\!!rotateaboutpivot#1#2{%
  2561.   \!dimenA=#1\relax  \advance\!dimenA -\!xpivot
  2562.   \!dimenB=#2\relax  \advance\!dimenB -\!ypivot
  2563.   \!dimenC=\!cosrotationangle\!dimenA
  2564.     \advance \!dimenC -\!sinrotationangle\!dimenB
  2565.   \!dimenD=\!cosrotationangle\!dimenB
  2566.     \advance \!dimenD  \!sinrotationangle\!dimenA
  2567.   \advance\!dimenC \!xpivot  \advance\!dimenD \!ypivot
  2568.   #1=\!dimenC  #2=\!dimenD
  2569.   \ignorespaces}
  2570. % ** \!!rotateonly{XREG}{YREG}
  2571. % ** Like \!!rotateaboutpivot, but with a pivot of  (0,0)
  2572. \def\!!rotateonly#1#2{%
  2573.   \!dimenA=#1\relax  \!dimenB=#2\relax 
  2574.   \!dimenC=\!cosrotationangle\!dimenA
  2575.     \advance \!dimenC -\!rotsign\!sinrotationangle\!dimenB
  2576.   \!dimenD=\!cosrotationangle\!dimenB
  2577.     \advance \!dimenD  \!rotsign\!sinrotationangle\!dimenA
  2578.   #1=\!dimenC  #2=\!dimenD
  2579.   \ignorespaces}
  2580. \def\!rotsign{}
  2581. \def\!!!rotateaboutpivot#1#2{\relax}
  2582. \def\!!!rotateonly#1#2{\relax}
  2583. \stoprotation
  2584. \def\!reverserotateonly#1#2{%
  2585.   \def\!rotsign{-}%
  2586.   \!rotateonly{#1}{#2}%
  2587.   \def\!rotsign{}%
  2588.   \ignorespaces}
  2589. % **********************************
  2590. % *** SHADING  (Handles shading) ***
  2591. % **********************************
  2592. % **  User commands
  2593. % **    \setshadegrid [span <SPAN>] [point at XSHADE YSHADE] 
  2594. % **    \setshadesymbol [<LS, RS, BS, TS>] ({SHADESYMBOL}
  2595. % **      <XDIMEN,YDIMEN> [ORIENTATION])
  2596. % **  Internal commands:
  2597. % **    \!startvshade  (xS,ybS,ytS)
  2598. % **    \!starthshade  (yS,xlS,xrS)
  2599. % **    \!lshade [<LS,RS,BS,TS>]
  2600. % **       ** when shading vertically:
  2601. % **       [the region from (xS,ybS,ytS) to] (xE,ybE,ytE)
  2602. % **       ** when shading horizontally:
  2603. % **       [the region from (yS,xlS,xrS) to] (yE,xlE,xrE)
  2604. % **    \!qshade [<LS,RS,BS,TS>]
  2605. % **       ** when shading vertically:
  2606. % **       [the region from (xS,ybS,ytS) to] (xM,ybM,ytM)  (xE,ybE,ytE)
  2607. % **       ** when shading horizontally:
  2608. % **       [the region from (yS,xlS,xrS) to] (yM,xlM,xrM)  (yE,xlE,xrE)
  2609. % **    \!lattice{ANCHOR}{SPAN}{LOCATION}{INDEX}{LATTICE LOCATION}
  2610. % **    \!override{NOMINAL DIMEN}{REPLACEMENT DIMEN}{DIMEN}
  2611. % **  The shading routine can operate either in a "vertical mode" or a
  2612. % **  "horizontal mode".  In vertical mode, the region to be shaded is specified
  2613. % **  in the form
  2614. % **                 {(x,y): xl <= x <= xr  &  yb(x) <= y <= yt(x)}
  2615. % **  where  yb  and  yt  are functions of  x.  In horizontal mode, the region
  2616. % **  is specified in the form
  2617. % **                 {(x,y): yb <= y <= yt  &  xl(y) <= x <= xr(y)}.
  2618. % **  The functions  yb  and  yt  may be either both linear or both quadratic;
  2619. % **  similarly for  xl  and  xr.  A region with say, piecewise quadratic bottom
  2620. % **  and top boundaries, can be shaded by consecutive (vertical) \!qshades,
  2621. % **  proceeding from left to right.  Similarly, a region with piecewise     
  2622. % **  quadratic left and right boundaries can be shaded by consecutive
  2623. % **  (horizontal) \!qshades, proceeding from bottom to top.  More complex
  2624. % **  regions can be shaded by partitioning them into appropriate subregions,
  2625. % **  and shading those.
  2626. % **  Shading is accomplished by placing a user-selected shading symbol at
  2627. % **  those points of a regular grid which fall within the region to be
  2628. % **  shaded.  This region can be "shrunk" so that a largish shading symbol
  2629. % **  will not extend outside it.  Shrinking is accomplished by specifying
  2630. % **  shrinkages for the left, right, bottom, and top boundaries, in a manner
  2631. % **  discussed further below.
  2632. % **  \shades and \!joins MUST NOT be intermingled.  Finish drawing a curve
  2633. % **  before starting to shade a region, and finish shading a region before
  2634. % **  starting to draw a curve.
  2635. % **  \setshadegrid [span <SPAN>] [point at XSHADE YSHADE] 
  2636. % **  The shading symbol is placed down on the points of a grid centered
  2637. % **  at the coordinate point (XSHADE,YSHADE).  The grid points are of the
  2638. % **  form (j*SPAN,k*SPAN), with  j+k  even.  SPAN is specified
  2639. % **  as a dimension.
  2640. % **  (XSHADE,YSHADE) defaults to previous (XSHADE,YSHADE) (or (0,0) if none)
  2641. % **  SPAN defaults to previous span (or 5pt if none)
  2642. % **  See Subsection 7.2 of the manual.
  2643. \def\setshadegrid{%
  2644.   \!ifnextchar{s}{\!getspan }
  2645.     {\!getspan span <\!dshade>}}
  2646. \def\!getspan span <#1>{%
  2647.   \!dshade=#1\relax
  2648.   \!ifcoordmode 
  2649.     \let\!GRnext=\!GRccheckforAP
  2650.   \else
  2651.     \let\!GRnext=\!GRdcheckforAP
  2652.   \fi
  2653.   \!GRnext}
  2654. \def\!GRccheckforAP{%
  2655.   \!ifnextchar{p}{\!cgetanchor }
  2656.     {\!cgetanchor point at {\!xshadesave} {\!yshadesave} }}
  2657. \def\!cgetanchor point at #1 #2 {%
  2658.   \edef\!xshadesave{#1}\edef\!yshadesave{#2}%
  2659.   \!xshade=\!xshadesave\!xunit  \!yshade=\!yshadesave\!yunit
  2660.   \ignorespaces}
  2661. \def\!GRdcheckforAP{%
  2662.   \!ifnextchar{p}{\!dgetanchor}%
  2663.     {\ignorespaces}}
  2664. \def\!dgetanchor point at #1 #2 {%
  2665.   \!xshade=#1\relax  \!yshade=#2\relax
  2666.   \ignorespaces}
  2667. % **  \setshadesymbol  [<LS, RS, BS, TS>] ({SHADESYMBOL}
  2668. % **    <XDIMEN,YDIMEN> [ORIENTATION])
  2669. % **  Saves SHADESYMBOL away in an hbox for use with shading routines.
  2670. % **  A shade symbol will not be plotted if its plot position comes within
  2671. % **    distance LS of the left boundary,  RS of the right boundary,  TS of the
  2672. % **    top boundary,  BS of the bottom boundary.  These parameters have 
  2673. % **    default values that should work in most cases (see below).
  2674. % **    To override a default value, specify the replacement value
  2675. % **    in the appropriate subfield of the shrinkages field.
  2676. % **    0pt may be coded as  "z" (without the quotes).  To accept a
  2677. % **    default value, leave the field empty.  Thus
  2678. % **      [,z,,5pt]  sets  LS=default, RS=0pt, BS=default, TS=5pt .
  2679. % **    Skipping the shrinkages field accepts all the defaults.
  2680. % **  See Subsection 7.1 of the manual.
  2681. \def\setshadesymbol{%
  2682.   \!ifnextchar<{\!setshadesymbol}{\!setshadesymbol<,,,> }}
  2683. \def\!setshadesymbol <#1,#2,#3,#4> (#5#6){%
  2684. % **  set the shadesymbol
  2685.   \!setputobject{#5}{#6}%                        
  2686.   \setbox\!shadesymbol=\box\!putobject%
  2687.   \!shadesymbolxshift=\!xshift \!shadesymbolyshift=\!yshift
  2688. % **  set the shrinkages
  2689.   \!dimenA=\!xshift \advance\!dimenA \!smidge% ** default LS = xshift - smidge
  2690.   \!override\!dimenA{#1}\!lshrinkage%         
  2691.   \!dimenA=\!wd \advance \!dimenA -\!xshift%   ** default RS = width - xshift
  2692.     \advance\!dimenA \!smidge%                                  - smidge
  2693.     \!override\!dimenA{#2}\!rshrinkage
  2694.   \!dimenA=\!dp \advance \!dimenA \!yshift%    ** default BS = depth + yshift
  2695.     \advance\!dimenA \!smidge%                                  - smidge
  2696.     \!override\!dimenA{#3}\!bshrinkage
  2697.   \!dimenA=\!ht \advance \!dimenA -\!yshift%   ** default TS = height - yshift
  2698.     \advance\!dimenA \!smidge%                                  - smidge
  2699.     \!override\!dimenA{#4}\!tshrinkage
  2700.   \ignorespaces}
  2701. \def\!smidge{-.2pt}%
  2702. % ** \!override{NOMINAL DIMEN}{REPLACEMENT DIMEN}{DIMEN}
  2703. % ** Overrides the NOMINAL DIMEN by the REPLACEMENT DIMEN to produce DIMEN,
  2704. % ** according to the following rules:
  2705. % **   REPLACEMENT DIMEN empty: DIMEN <-- NOMINAL DIMEN
  2706. % **   REPLACEMENT DIMEN z:     DIMEN <-- 0pt
  2707. % **   otherwise:               DIMEN <-- REPLACEMENT DIMEN
  2708. % ** DIMEN must be a dimension register
  2709. \def\!override#1#2#3{%
  2710.   \edef\!!override{#2}% 
  2711.   \ifx \!!override\empty
  2712.     #3=#1\relax
  2713.   \else
  2714.     \if z\!!override
  2715.       #3=\!zpt
  2716.     \else
  2717.       \ifx \!!override\!blankz
  2718.         #3=\!zpt
  2719.       \else
  2720.         #3=#2\relax
  2721.       \fi
  2722.     \fi
  2723.   \fi
  2724.   \ignorespaces}
  2725. \def\!blankz{ z}
  2726. \setshadesymbol ({\fiverm .})%       ** initialize plotsymbol
  2727. %                                    ** \fivesy ^^B  is a small cross
  2728. % ** \!startvshade [at] (xS,ybS,ytS)
  2729. % ** Initiates vertical shading mode
  2730. \def\!startvshade#1(#2,#3,#4){%
  2731.   \let\!!xunit=\!xunit%
  2732.   \let\!!yunit=\!yunit%
  2733.   \let\!!xshade=\!xshade%
  2734.   \let\!!yshade=\!yshade%
  2735.   \def\!getshrinkages{\!vgetshrinkages}%
  2736.   \let\!setshadelocation=\!vsetshadelocation%
  2737.   \!xS=\!M{#2}\!!xunit
  2738.   \!ybS=\!M{#3}\!!yunit
  2739.   \!ytS=\!M{#4}\!!yunit
  2740.   \!shadexorigin=\!xorigin  \advance \!shadexorigin \!shadesymbolxshift
  2741.   \!shadeyorigin=\!yorigin  \advance \!shadeyorigin \!shadesymbolyshift
  2742.   \ignorespaces}
  2743. % ** \!starthshade [at] (yS,xlS,xrS)
  2744. % ** Initiates horizontal shading mode
  2745. \def\!starthshade#1(#2,#3,#4){%
  2746.   \let\!!xunit=\!yunit%
  2747.   \let\!!yunit=\!xunit%
  2748.   \let\!!xshade=\!yshade%
  2749.   \let\!!yshade=\!xshade%
  2750.   \def\!getshrinkages{\!hgetshrinkages}%
  2751.   \let\!setshadelocation=\!hsetshadelocation%
  2752.   \!xS=\!M{#2}\!!xunit
  2753.   \!ybS=\!M{#3}\!!yunit
  2754.   \!ytS=\!M{#4}\!!yunit
  2755.   \!shadexorigin=\!xorigin  \advance \!shadexorigin \!shadesymbolxshift
  2756.   \!shadeyorigin=\!yorigin  \advance \!shadeyorigin \!shadesymbolyshift
  2757.   \ignorespaces}
  2758. % **  \!lattice{ANCHOR}{SPAN}{LOCATION}{INDEX}{LATTICE LOCATION}
  2759. % **  Consider the lattice with points  ANCHOR + j*SPAN. This routine determines
  2760. % **  the index  k  of the smallest lattice point >= LOCATION, and sets
  2761. % **  LATTICE LOCATION = ANCHOR + k*SPAN.
  2762. % **  INDEX is assumed to be a count register, LATTICE LOCATION a dimen reg.
  2763. \def\!lattice#1#2#3#4#5{%
  2764.   \!dimenA=#1%                        ** dimA = ANCHOR
  2765.   \!dimenB=#2%                        ** dimB = SPAN  (assumed > 0pt)
  2766.   \!countB=\!dimenB%                  ** ctB  = SPAN, as a count
  2767. % ** Determine index of smallest lattice point >= LOCATION
  2768.   \!dimenC=#3%                        ** dimC = LOCATION
  2769.   \advance\!dimenC -\!dimenA%         ** now dimC = LOCATION-ANCHOR
  2770.   \!countA=\!dimenC%                  ** ctA = above, as a count
  2771.   \divide\!countA \!countB%           ** now ctA = desired index, if dimC <= 0
  2772.   \ifdim\!dimenC>\!zpt
  2773.     \!dimenD=\!countA\!dimenB%        ** (tentative k)*span
  2774.     \ifdim\!dimenD<\!dimenC%          ** if this is false, ctA = desired index
  2775.       \advance\!countA 1 %            ** if true, have to add 1
  2776.     \fi
  2777.   \fi
  2778.   \!dimenC=\!countA\!dimenB%          ** lattice location = anchor + ctA*span
  2779.     \advance\!dimenC \!dimenA
  2780.   #4=\!countA%                        ** the desired index
  2781.   #5=\!dimenC%                        ** corresponding lattice location
  2782.   \ignorespaces}
  2783. % ** \!qshade [with shrinkages] [[LS,RS,BS,TS]]
  2784. % ***** during vertical shading:
  2785. % **    [the region from (xS,ybS,ytS) to] (xM,ybM,ytM) [and] (xE,ybE,ytE)
  2786. % ** Shades the region {(x,y): xS <= x <= xE, yb(x) <= y <= yt(x)}, where 
  2787. % **   yb is the quadratic thru (xS,ybS) & (xM,ybM) & (xE,ybE)
  2788. % **   yt is the quadratic thru (xS,ytS) & (xM,ybM) & (xE,ytE)
  2789. % ** xS,ybS,ytS are either given by \!startvshade or carried over
  2790. % **   as the ending values of the immediately preceding \!qshade.
  2791. % ** For the interpretation of LS, RS, BS, & TS, see \setshadesymbol. The
  2792. % **   values set there can be overridden, for the course of this \!qshade
  2793. % **   only, in the same manner as overrides are specified for
  2794. % **   \setshadesymbol.
  2795. % ***** during horizontal shading:
  2796. % **    [the region from (yS,xlS,xrS) to] (yM,xlM,xrM) [and] (yE,xlE,xrE)
  2797. \def\!qshade#1(#2,#3,#4)#5(#6,#7,#8){%
  2798.   \!xM=\!M{#2}\!!xunit
  2799.   \!ybM=\!M{#3}\!!yunit
  2800.   \!ytM=\!M{#4}\!!yunit
  2801.   \!xE=\!M{#6}\!!xunit
  2802.   \!ybE=\!M{#7}\!!yunit
  2803.   \!ytE=\!M{#8}\!!yunit
  2804.   \!getcoeffs\!xS\!ybS\!xM\!ybM\!xE\!ybE\!ybB\!ybC%**Get coefficients B & C for
  2805.   \!getcoeffs\!xS\!ytS\!xM\!ytM\!xE\!ytE\!ytB\!ytC%**y=y0 + B(x-X0) + C(x-X0)**2
  2806.   \def\!getylimits{\!qgetylimits}%
  2807.   \!shade{#1}\ignorespaces}
  2808. % ** \!lshade ... (xE,ybE,ytE)
  2809. % ** This is like \!qshade, but the top and bottom boundaries are linear,
  2810. % ** rather than quadratic.
  2811. \def\!lshade#1(#2,#3,#4){%
  2812.   \!xE=\!M{#2}\!!xunit
  2813.   \!ybE=\!M{#3}\!!yunit
  2814.   \!ytE=\!M{#4}\!!yunit
  2815.   \!dimenE=\!xE  \advance \!dimenE -\!xS%   ** xE-xS
  2816.   \!dimenC=\!ytE \advance \!dimenC -\!ytS%  ** ytE-ytS
  2817.   \!divide\!dimenC\!dimenE\!ytB%            ** ytB = (ytE-ytS)/(xE-xS)
  2818.   \!dimenC=\!ybE \advance \!dimenC -\!ybS%  ** ybE-ybS
  2819.   \!divide\!dimenC\!dimenE\!ybB%            ** ybB = (ybE-ybS)/(xE-xS)
  2820.   \def\!getylimits{\!lgetylimits}%
  2821.   \!shade{#1}\ignorespaces}
  2822. % **  \!getcoeffs{X0}{Y0}{X1}{Y1}{X2}{Y2}{B}{C}
  2823. % **  Finds  B  and  C  such that the quadratic  y = Y0 + B(x-X0) + C(x-X0)**2
  2824. % **  passes through (X1,Y1) and (X2,Y2):  when X0=0=Y0, the formulas are:
  2825. % **                   B = S1 - X1*C,   C = (S2-S1)/X2
  2826. % **  with
  2827. % **                 S1 = Y1/X1,   S2 = (Y2-Y1)/(X2-X1).
  2828. \def\!getcoeffs#1#2#3#4#5#6#7#8{% 
  2829.   \!dimenC=#4\advance \!dimenC -#2%            ** dimC=Y1-Y0
  2830.   \!dimenE=#3\advance \!dimenE -#1%            ** dimE=X1-X0
  2831.   \!divide\!dimenC\!dimenE\!dimenF%            ** dimF=S1
  2832.   \!dimenC=#6\advance \!dimenC -#4%            ** dimC=Y2-Y1
  2833.   \!dimenH=#5\advance \!dimenH -#3%            ** dimH=X2-X1
  2834.   \!divide\!dimenC\!dimenH\!dimenG%            ** dimG=S2
  2835.   \advance\!dimenG -\!dimenF%                  ** dimG=S2-S1
  2836.   \advance \!dimenH \!dimenE%                  ** dimH=X2-X0
  2837.   \!divide\!dimenG\!dimenH#8%                  ** C=(S2-S1)/(X2-X0)
  2838.   \!removept#8\!t%                             ** C, without "pt"
  2839.   #7=-\!t\!dimenE%                             ** -C*(X1-X0)
  2840.   \advance #7\!dimenF%                         ** B=S1-C*(X1-X0)
  2841.   \ignorespaces}
  2842. \def\!shade#1{%
  2843. % ** Get LS,RS,BS,TS for this panel
  2844.   \!getshrinkages#1<,,,>\!nil% %       ** now effective LS=dimE, RS=dimF,
  2845. %                                      **   BS=dimG, TS=dimH
  2846.   \advance \!dimenE \!xS%              ** now dimE=xS+LS
  2847.   \!lattice\!!xshade\!dshade\!dimenE%  ** set parity=index of left-mst x-lattice
  2848.     \!parity\!xpos%                    **   point >= xS+LS, xpos=its location
  2849.   \!dimenF=-\!dimenF%                  ** set dimF=xE-RS
  2850.     \advance\!dimenF \!xE
  2851. %               
  2852.   \!loop\!not{\ifdim\!xpos>\!dimenF}%  ** loop over x-lattice points <= xE-RS
  2853.     \!shadecolumn%                 
  2854.     \advance\!xpos \!dshade%           ** move over to next column
  2855.     \advance\!parity 1%                ** increase index of x-point
  2856.   \repeat
  2857.   \!xS=\!xE%                           ** shift ending values to starting values
  2858.   \!ybS=\!ybE
  2859.   \!ytS=\!ytE
  2860.   \ignorespaces}
  2861. \def\!vgetshrinkages#1<#2,#3,#4,#5>#6\!nil{%
  2862.   \!override\!lshrinkage{#2}\!dimenE
  2863.   \!override\!rshrinkage{#3}\!dimenF
  2864.   \!override\!bshrinkage{#4}\!dimenG
  2865.   \!override\!tshrinkage{#5}\!dimenH
  2866.   \ignorespaces}
  2867. \def\!hgetshrinkages#1<#2,#3,#4,#5>#6\!nil{%
  2868.   \!override\!lshrinkage{#2}\!dimenG
  2869.   \!override\!rshrinkage{#3}\!dimenH
  2870.   \!override\!bshrinkage{#4}\!dimenE
  2871.   \!override\!tshrinkage{#5}\!dimenF
  2872.   \ignorespaces}
  2873. \def\!shadecolumn{%
  2874.   \!dxpos=\!xpos
  2875.   \advance\!dxpos -\!xS%            ** dx = x - xS
  2876.   \!removept\!dxpos\!dx%            ** ditto, without "pt"
  2877.   \!getylimits%                     ** get top and bottom y-values
  2878.   \advance\!ytpos -\!dimenH%        ** less TS
  2879.   \advance\!ybpos \!dimenG%         ** plus BS
  2880.   \!yloc=\!!yshade%                 ** get anchor point for this column
  2881.   \ifodd\!parity 
  2882.      \advance\!yloc \!dshade
  2883.   \fi
  2884.   \!lattice\!yloc{2\!dshade}\!ybpos%
  2885.     \!countA\!ypos%                 ** ypos=smallest y point for this column
  2886.   \!dimenA=-\!shadexorigin \advance \!dimenA \!xpos%      ** over
  2887.   \loop\!not{\ifdim\!ypos>\!ytpos}% ** loop over ypos <= yt(t)
  2888.     \!setshadelocation%             ** vmode: xloc=xpos, yloc=ypos 
  2889. %                                   ** hmode: xloc=ypos, yloc=xpos 
  2890.     \!rotateaboutpivot\!xloc\!yloc%
  2891.     \!dimenA=-\!shadexorigin \advance \!dimenA \!xloc%    ** over
  2892.     \!dimenB=-\!shadeyorigin \advance \!dimenB \!yloc%    ** up
  2893.     \kern\!dimenA \raise\!dimenB\copy\!shadesymbol \kern-\!dimenA
  2894.     \advance\!ypos 2\!dshade
  2895.   \repeat
  2896.   \ignorespaces}
  2897. \def\!qgetylimits{%
  2898.   \!dimenA=\!dx\!ytC              
  2899.   \advance\!dimenA \!ytB%         ** yt(t)=ytS + dx*(Bt + dx*Ct)
  2900.   \!ytpos=\!dx\!dimenA
  2901.   \advance\!ytpos \!ytS
  2902.   \!dimenA=\!dx\!ybC              
  2903.   \advance\!dimenA \!ybB%         ** yb(t)=ybS + dx*(Bb + dx*Cb)
  2904.   \!ybpos=\!dx\!dimenA
  2905.   \advance\!ybpos \!ybS}
  2906. \def\!lgetylimits{%
  2907.   \!ytpos=\!dx\!ytB%              ** yt(t)=ytS + dx*Bt
  2908.   \advance\!ytpos \!ytS
  2909.   \!ybpos=\!dx\!ybB%              ** yb(t)=ybS + dx*Bb
  2910.   \advance\!ybpos \!ybS}
  2911. \def\!vsetshadelocation{%         ** vmode: xloc=xpos, yloc=ypos 
  2912.   \!xloc=\!xpos
  2913.   \!yloc=\!ypos}
  2914. \def\!hsetshadelocation{%         ** hmode: xloc=ypos, yloc=xpos 
  2915.   \!xloc=\!ypos
  2916.   \!yloc=\!xpos}
  2917. % **************************************
  2918. % *** TICKS  (Draws ticks on graphs) ***
  2919. % **************************************
  2920. % ** User commands
  2921. % **   \ticksout
  2922. % **   \ticksin
  2923. % **   \gridlines
  2924. % **   \nogridlines
  2925. % **   \loggedticks
  2926. % **   \unloggesticks
  2927. % ** See Subsection 3.4 of the manual
  2928. % ** The following is an option of the \axis command
  2929. % **   ticks 
  2930. % **     [in] [out] 
  2931. % **     [long] [short] [length <LENGTH>] 
  2932. % **     [width <WIDTH>]
  2933. % **     [andacross] [butnotacross] 
  2934. % **     [logged] [unlogged] 
  2935. % **     [unlabeled] [numbered] [withvalues VALUE1 VALUE2 ... VALUEk / ]
  2936. % **     [quantity Q] [at LOC1 LOC2 ... LOCk / ] [from LOC1 to LOC2 by
  2937. % **       LOC_INCREMENT]
  2938. % ** See Subsection 3.2 of the manual for the rules.
  2939. % ** The various options of the  tick  field are processed by the
  2940. % ** \!nextkeyword  command defined below.
  2941. % ** For example, `\!nextkeyword short '  expands to  `\!ticksshort',
  2942. % ** while `\!nextkeyword withvalues' expands to `\!tickswithvalues'.
  2943. \def\!axisticks {%
  2944.   \def\!nextkeyword##1 {%
  2945.     \expandafter\ifx\csname !ticks##1\endcsname \relax
  2946.       \def\!next{\!fixkeyword{##1}}%
  2947.     \else
  2948.       \def\!next{\csname !ticks##1\endcsname}%
  2949.     \fi
  2950.     \!next}%
  2951.   \!axissetup
  2952.     \def\!axissetup{\relax}%
  2953.   \edef\!ticksinoutsign{\!ticksinoutSign}%
  2954.   \!ticklength=\longticklength
  2955.   \!tickwidth=\linethickness
  2956.   \!gridlinestatus
  2957.   \!setticktransform
  2958.   \!maketick
  2959.   \!tickcase=0
  2960.   \def\!LTlist{}%
  2961.   \!nextkeyword}
  2962. \def\ticksout{%
  2963.   \def\!ticksinoutSign{+}}
  2964. \def\ticksin{%
  2965.   \def\!ticksinoutSign{-}}
  2966. \ticksout
  2967. \def\gridlines{%
  2968.   \def\!gridlinestatus{\!gridlinestootrue}}
  2969. \def\nogridlines{%
  2970.   \def\!gridlinestatus{\!gridlinestoofalse}}
  2971. \nogridlines
  2972. \def\loggedticks{%
  2973.   \def\!setticktransform{\let\!ticktransform=\!logten}}
  2974. \def\unloggedticks{%
  2975.   \def\!setticktransform{\let\!ticktransform=\!donothing}}
  2976. \def\!donothing#1#2{\def#2{#1}}
  2977. \unloggedticks
  2978. % ** \!ticks/ : terminates read of tick options
  2979. \expandafter\def\csname !ticks/\endcsname{%
  2980.   \!not {\ifx \!LTlist\empty}
  2981.     \!placetickvalues
  2982.   \fi
  2983.   \def\!tickvalueslist{}%
  2984.   \def\!LTlist{}%
  2985.   \expandafter\csname !axis/\endcsname}
  2986. \def\!maketick{%
  2987.   \setbox\!boxA=\hbox{%
  2988.     \beginpicture
  2989.       \!setdimenmode
  2990.       \setcoordinatesystem point at {\!zpt} {\!zpt}   
  2991.       \linethickness=\!tickwidth
  2992.       \ifdim\!ticklength>\!zpt
  2993.         \putrule from {\!zpt} {\!zpt} to
  2994.           {\!ticksinoutsign\!tickxsign\!ticklength}
  2995.           {\!ticksinoutsign\!tickysign\!ticklength}
  2996.       \fi
  2997.       \if!gridlinestoo
  2998.         \putrule from {\!zpt} {\!zpt} to
  2999.           {-\!tickxsign\!xaxislength} {-\!tickysign\!yaxislength}
  3000.       \fi
  3001.     \endpicturesave <\!Xsave,\!Ysave>}%
  3002.     \wd\!boxA=\!zpt}
  3003. \def\!ticksin{%
  3004.   \def\!ticksinoutsign{-}%
  3005.   \!maketick
  3006.   \!nextkeyword}
  3007. \def\!ticksout{%
  3008.   \def\!ticksinoutsign{+}%
  3009.   \!maketick
  3010.   \!nextkeyword}
  3011. \def\!tickslength<#1> {%
  3012.   \!ticklength=#1\relax
  3013.   \!maketick
  3014.   \!nextkeyword}
  3015. \def\!tickslong{%
  3016.   \!tickslength<\longticklength> }
  3017. \def\!ticksshort{%
  3018.   \!tickslength<\shortticklength> }
  3019. \def\!tickswidth<#1> {%
  3020.   \!tickwidth=#1\relax
  3021.   \!maketick
  3022.   \!nextkeyword}
  3023. \def\!ticksandacross{%
  3024.   \!gridlinestootrue
  3025.   \!maketick
  3026.   \!nextkeyword}
  3027. \def\!ticksbutnotacross{%
  3028.   \!gridlinestoofalse
  3029.   \!maketick
  3030.   \!nextkeyword}
  3031. \def\!tickslogged{%
  3032.   \let\!ticktransform=\!logten
  3033.   \!nextkeyword}
  3034. \def\!ticksunlogged{%
  3035.   \let\!ticktransform=\!donothing
  3036.   \!nextkeyword}
  3037. \def\!ticksunlabeled{%
  3038.   \!tickcase=0
  3039.   \!nextkeyword}
  3040. \def\!ticksnumbered{%
  3041.   \!tickcase=1
  3042.   \!nextkeyword}
  3043. \def\!tickswithvalues#1/ {%
  3044.   \edef\!tickvalueslist{#1! /}%
  3045.   \!tickcase=2
  3046.   \!nextkeyword}
  3047. \def\!ticksquantity#1 {%
  3048.   \ifnum #1>1
  3049.     \!updatetickoffset
  3050.     \!countA=#1\relax
  3051.     \advance \!countA -1
  3052.     \!ticklocationincr=\!axisLength
  3053.       \divide \!ticklocationincr \!countA
  3054.     \!ticklocation=\!axisstart
  3055.     \loop \!not{\ifdim \!ticklocation>\!axisend}
  3056.       \!placetick\!ticklocation
  3057.       \ifcase\!tickcase
  3058.           \relax %  Case 0: no labels
  3059.         \or
  3060.           \relax %  Case 1: numbered -- not available here
  3061.         \or
  3062.           \expandafter\!gettickvaluefrom\!tickvalueslist
  3063.           \edef\!tickfield{{\the\!ticklocation}{\!value}}%
  3064.           \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3065.       \fi
  3066.       \advance \!ticklocation \!ticklocationincr
  3067.     \repeat
  3068.   \fi
  3069.   \!nextkeyword}
  3070. \def\!ticksat#1 {%
  3071.   \!updatetickoffset
  3072.   \edef\!Loc{#1}%
  3073.   \if /\!Loc
  3074.     \def\next{\!nextkeyword}%
  3075.   \else
  3076.     \!ticksincommon
  3077.     \def\next{\!ticksat}%
  3078.   \fi
  3079.   \next}    
  3080.       
  3081. \def\!ticksfrom#1 to #2 by #3 {%
  3082.   \!updatetickoffset
  3083.   \edef\!arg{#3}%
  3084.   \expandafter\!separate\!arg\!nil
  3085.   \!scalefactor=1
  3086.   \expandafter\!countfigures\!arg/
  3087.   \edef\!arg{#1}%
  3088.   \!scaleup\!arg by\!scalefactor to\!countE
  3089.   \edef\!arg{#2}%
  3090.   \!scaleup\!arg by\!scalefactor to\!countF
  3091.   \edef\!arg{#3}%
  3092.   \!scaleup\!arg by\!scalefactor to\!countG
  3093.   \loop \!not{\ifnum\!countE>\!countF}
  3094.     \ifnum\!scalefactor=1
  3095.       \edef\!Loc{\the\!countE}%
  3096.     \else
  3097.       \!scaledown\!countE by\!scalefactor to\!Loc
  3098.     \fi
  3099.     \!ticksincommon
  3100.     \advance \!countE \!countG
  3101.   \repeat
  3102.   \!nextkeyword}
  3103. \def\!updatetickoffset{%
  3104.   \!dimenA=\!ticksinoutsign\!ticklength
  3105.   \ifdim \!dimenA>\!offset
  3106.     \!offset=\!dimenA
  3107.   \fi}
  3108. \def\!placetick#1{%
  3109.   \if!xswitch
  3110.     \!xpos=#1\relax
  3111.     \!ypos=\!axisylevel
  3112.   \else
  3113.     \!xpos=\!axisxlevel
  3114.     \!ypos=#1\relax
  3115.   \fi
  3116.   \advance\!xpos \!Xsave
  3117.   \advance\!ypos \!Ysave
  3118.   \kern\!xpos\raise\!ypos\copy\!boxA\kern-\!xpos
  3119.   \ignorespaces}
  3120. \def\!gettickvaluefrom#1 #2 /{%
  3121.   \edef\!value{#1}%
  3122.   \edef\!tickvalueslist{#2 /}%
  3123.   \ifx \!tickvalueslist\!endtickvaluelist
  3124.     \!tickcase=0
  3125.   \fi}
  3126. \def\!endtickvaluelist{! /}
  3127. \def\!ticksincommon{%
  3128.   \!ticktransform\!Loc\!t
  3129.   \!ticklocation=\!t\!!unit
  3130.   \advance\!ticklocation -\!!origin
  3131.   \!placetick\!ticklocation
  3132.   \ifcase\!tickcase
  3133.     \relax % Case 0: no labels
  3134.   \or %      Case 1: numbered
  3135.     \ifdim\!ticklocation<-\!!origin
  3136.       \edef\!Loc{$\!Loc$}%
  3137.     \fi
  3138.     \edef\!tickfield{{\the\!ticklocation}{\!Loc}}%
  3139.     \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3140.   \or %      Case 2: labeled
  3141.     \expandafter\!gettickvaluefrom\!tickvalueslist
  3142.     \edef\!tickfield{{\the\!ticklocation}{\!value}}%
  3143.     \expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
  3144.   \fi}
  3145. \def\!separate#1\!nil{%
  3146.   \!ifnextchar{-}{\!!separate}{\!!!separate}#1\!nil}
  3147. \def\!!separate-#1\!nil{%
  3148.   \def\!sign{-}%
  3149.   \!!!!separate#1..\!nil}
  3150. \def\!!!separate#1\!nil{%
  3151.   \def\!sign{+}%
  3152.   \!!!!separate#1..\!nil}
  3153. \def\!!!!separate#1.#2.#3\!nil{%
  3154.   \def\!arg{#1}%
  3155.   \ifx\!arg\!empty
  3156.     \!countA=0
  3157.   \else
  3158.     \!countA=\!arg
  3159.   \fi
  3160.   \def\!arg{#2}%
  3161.   \ifx\!arg\!empty
  3162.     \!countB=0
  3163.   \else
  3164.     \!countB=\!arg
  3165.   \fi}
  3166. \def\!countfigures#1{%
  3167.   \if #1/%
  3168.     \def\!next{\ignorespaces}%
  3169.   \else
  3170.     \multiply\!scalefactor 10
  3171.     \def\!next{\!countfigures}%
  3172.   \fi
  3173.   \!next}
  3174. \def\!scaleup#1by#2to#3{%
  3175.   \expandafter\!separate#1\!nil
  3176.   \multiply\!countA #2\relax
  3177.   \advance\!countA \!countB
  3178.   \if -\!sign
  3179.     \!countA=-\!countA
  3180.   \fi
  3181.   #3=\!countA
  3182.   \ignorespaces}
  3183. \def\!scaledown#1by#2to#3{%
  3184.   \!countA=#1\relax%                          ** get original #
  3185.   \ifnum \!countA<0 %                         ** take abs value,
  3186.     \def\!sign{-}%                            **   remember sign
  3187.     \!countA=-\!countA
  3188.   \else
  3189.     \def\!sign{}%
  3190.   \fi
  3191.   \!countB=\!countA%                          ** copy |#|
  3192.   \divide\!countB #2\relax%                   ** integer part (|#|/sf)
  3193.   \!countC=\!countB%                          ** get sf * (|#|/sf)
  3194.     \multiply\!countC #2\relax
  3195.   \advance \!countA -\!countC%                ** ctA is now remainder
  3196.   \edef#3{\!sign\the\!countB.}%               ** +- integerpart.
  3197.   \!countC=\!countA %                         ** Tack on proper number
  3198.   \ifnum\!countC=0 %                          **   of zeros after .
  3199.     \!countC=1
  3200.   \fi
  3201.   \multiply\!countC 10
  3202.   \!loop \ifnum #2>\!countC
  3203.     \edef#3{#3\!zero}%
  3204.     \multiply\!countC 10
  3205.   \repeat
  3206.   \edef#3{#3\the\!countA}%                    ** Add on rest of remainder
  3207.   \ignorespaces}
  3208. \def\!placetickvalues{%
  3209.   \advance\!offset \tickstovaluesleading
  3210.   \if!xswitch
  3211.     \setbox\!boxA=\hbox{%
  3212.       \def\\##1##2{%
  3213.         \!dimenput {##2} [B] (##1,\!axisylevel)}%
  3214.       \beginpicture 
  3215.         \!LTlist
  3216.       \endpicturesave <\!Xsave,\!Ysave>}%
  3217.     \!dimenA=\!axisylevel
  3218.       \advance\!dimenA -\!Ysave
  3219.       \advance\!dimenA \!tickysign\!offset
  3220.       \if -\!tickysign
  3221.         \advance\!dimenA -\ht\!boxA
  3222.       \else
  3223.         \advance\!dimenA  \dp\!boxA
  3224.       \fi
  3225.     \advance\!offset \ht\!boxA 
  3226.       \advance\!offset \dp\!boxA
  3227.     \!dimenput {\box\!boxA} [Bl] <\!Xsave,\!Ysave> (\!zpt,\!dimenA)
  3228.   \else
  3229.     \setbox\!boxA=\hbox{%
  3230.       \def\\##1##2{%
  3231.         \!dimenput {##2} [r] (\!axisxlevel,##1)}%
  3232.       \beginpicture 
  3233.         \!LTlist
  3234.       \endpicturesave <\!Xsave,\!Ysave>}%
  3235.     \!dimenA=\!axisxlevel
  3236.       \advance\!dimenA -\!Xsave
  3237.       \advance\!dimenA \!tickxsign\!offset
  3238.       \if -\!tickxsign
  3239.         \advance\!dimenA -\wd\!boxA
  3240.       \fi
  3241.     \advance\!offset \wd\!boxA
  3242.     \!dimenput {\box\!boxA} [Bl] <\!Xsave,\!Ysave> (\!dimenA,\!zpt)
  3243.   \fi}
  3244. \normalgraphs
  3245. \catcode`!=12 %  *****  THIS MUST NEVER BE OMITTED
  3246.